Select to view content in your preferred language

How can I get a custom widget to rerender when fields change

799
6
08-30-2023 11:09 AM
GBreen
by
Occasional Contributor

I've got a simple widget that toggles a boolean but it stays on false and never rerenders. What am I doing wrong?

 

 

 

import { property } from 'esri/core/accessorSupport/decorators';
import { tsx } from 'esri/widgets/support/widget';
import esriWidget = require('esri/widgets/Widget');

const CSS = {
	base: 'redline-widget esri-widget--panel esri-widget',
	button: 'btn btn-white btn-sm btn-primary pull-right',
	loading: 'esri-icon-loading-indicator esri-rotating'
};

class Test extends esriWidget {
	constructor(config: any) {
		super();

		setInterval(() => {
			this.processing = !this.processing;
		}, 5000);
	}

	@property()
	processing: boolean;

	render() {
		return (
			<div class={CSS.base}>
				{this.processing ? "True" : "False"}
			</div>
		);
	}
}

export = Test;

 

 

 

0 Kudos
6 Replies
GBreen
by
Occasional Contributor

Also in the docs they mention it's not recommended to extend Widget but if I don't it won't render at all except inside an expandable

0 Kudos
ReneRubalcava
Honored Contributor

We no longer recommend you extend the Widget class or build custom widgets with the Widget base.

It's recommended you use your preferred framework to build your components as shown here.

https://github.com/Esri/jsapi-resources/tree/main/esm-samples/jsapi-custom-ui

If you however, need to maintain a current widget, you need to use the subclass decorator to make reactivity work as show here.

0 Kudos
GBreen
by
Occasional Contributor

Yeah I'm trying to maintain and upgrade a suite of existing widgets but if I add a subclass to this widget like you suggest I get an error "TypeError: class constructors must be invoked with 'new'" when trying to create the widget:

 

return new TestWidget();

 

Any suggestions on that?

0 Kudos
ReneRubalcava
Honored Contributor

It might be your tsconfig settings too. This project works, see if it can help you out.

https://github.com/odoe/jsapi-ts-esm-widget

0 Kudos
ReneRubalcava
Honored Contributor

I just noticed you're using the "esri/" paths, so you must be using the AMD CDN.

In that case, I don't think you can use the 'extends', you need to use createSubclass.

The snippets here provide a dropdown to switch between TS and JS, and you can see what I mean.

https://developers.arcgis.com/javascript/latest/implementing-accessor/

ReneRubalcava_0-1693435642925.png

I haven't built custom widgets in this pattern, so not entirely sure, but that might be the way to go.

I did update my ESM widget sample with your code and it does work, so I think it's the createSubclass you need.

https://github.com/odoe/jsapi-ts-esm-widget/blob/main/src/test-widget.tsx

0 Kudos
JoelBennett
MVP Regular Contributor

This looks like a scope issue.  In your anonymous function called by setInterval, "this" will refer to the window, not the instance of the widget.  You should be able to get around this using bind:

window.setInterval(function() {
	this.processing = !this.processing;
}.bind(this), 5000);

 

0 Kudos