I have a global variable for highlight handles that I'm trying to watch to update a label with the number of currently selected features. However, the variable is initially undefined and this seems to be causing an issue. Even if I set the watch options to initial is true, the code will only execute the first time. Is there a way for me to run it initially and then continue to monitor once the variable is defined? This is my code:
reactiveUtils.watch(()=> globalThis.highlightHandles?._groups.size, () =>{
const numSelected = globalThis.highlightHandles?._groups.size;
selectedCount.innerText = numSelected;
console.log("Num selected is "+numSelected);
if (numSelected){
selectedCount.style.color = 'black';
moreActionsButton.disabled = false;
}
else {
selectedCount.innerText = "0";
selectedCount.style.color = '#c9c9c9';
moreActionsButton.disabled = true;
}
},{initial: true});Any help would be greatly appreciated!
Solved! Go to Solution.
The reactiveUtils only work against the SDK classes, not native objects and arrays, so we can't watch for changes on `globalThis`. The root object in the watchExpression needs to be an SDK class.
Try using a when before the watch. Might want to use a {once: true} for the when.
reactiveUtils.when(
() => globalThis.highlightHandles != null,
() => {
reactiveUtils.watch(
() => globalThis.highlightHandles._groups.size,
Unfortunately, that does not seem to work. This is the updated code:
reactiveUtils.when(()=> globalThis.highlightHandles != null, ()=>{
reactiveUtils.watch(()=> globalThis.highlightHandles._groups.size, () =>{
const numSelected = globalThis.highlightHandles._groups.size;
selectedCount.innerText = numSelected;
console.log("Num selected is "+numSelected);
if (numSelected){
selectedCount.style.color = 'black';
moreActionsButton.disabled = false;
}
else {
selectedCount.innerText = "0";
selectedCount.style.color = '#c9c9c9';
moreActionsButton.disabled = true;
}
});
});
Try creating the variable like this instead. Also _groups would make it private, so the API might not see it as observable.
reactiveUtils.when(
() => globalThis.highlightHandles != null,
() => {
reactiveUtils.watch(
() => globalThis.highlightHandles._groups.size,
(numSelected) => {...
This is one of those issues I usually slap a setTimeout() on.
setTimeout(()=> {
reactiveUtils.watch(()=> globalThis.highlightHandles._groups.size, () =>{
const numSelected = globalThis.highlightHandles._groups.size;
selectedCount.innerText = numSelected;
console.log("Num selected is "+numSelected);
if (numSelected){
selectedCount.style.color = 'black';
moreActionsButton.disabled = false;
}
else {
selectedCount.innerText = "0";
selectedCount.style.color = '#c9c9c9';
moreActionsButton.disabled = true;
}
});
}, 100)It's not a best practice, but it usually works. Try dialing up or down the wait a few times and see if it works.
The reactiveUtils only work against the SDK classes, not native objects and arrays, so we can't watch for changes on `globalThis`. The root object in the watchExpression needs to be an SDK class.
Thanks Rene. I did not realize it could only be used to track changes to the SDK objects. Since I am also using a feature table to highlight, I ended up just watching the featureTable.highlightIds.length property. This code worked for me:
reactiveUtils.watch(()=> featureTable.highlightIds.length, (numSelected) =>{
selectedCount.innerText = numSelected;
if (numSelected > 0){
selectedCount.style.color = 'black';
moreActionsButton.disabled = false;
}
else {
selectedCount.style.color = '#c9c9c9';
moreActionsButton.disabled = true;
}
});
Try this based off of @JeffreyThompson2 suggestion and what we have learned from @ReneRubalcava .
setInterval(() => {
const numSelected = globalThis.highlightHandles?._groups?.size || 0;
selectedCount.innerText = numSelected;
console.log("Num selected is " + numSelected);
if (numSelected) {
selectedCount.style.color = 'black';
moreActionsButton.disabled = false;
} else {
selectedCount.style.color = '#c9c9c9';
moreActionsButton.disabled = true;
}
}, 250);
You’ll probably need to watch the object after it’s assigned, because watch() can’t keep tracking an undefined reference reliably. A cleaner approach is to watch the property that changes, or re-register the watcher once highlightHandles gets initialized. The initial: true option only fires once with the current value — it doesn’t wait for future definition changes.
@FCTV33 You’ll probably need to watch the object after it’s assigned, because watch() can’t keep tracking an undefined reference reliably. A cleaner approach is to watch the property that changes, or re-register the watcher once highlightHandles gets initialized. The initial: true option only fires once with the current value — it doesn’t wait for future definition changes.