- update(options: VisualUpdateOptions): void
- destroy?(): void
- eumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration
|Here the slider sent an on change when the selected value was updated programmatically.|
The kicker is when your custom visual changes the selection and calls APF during a call to update(). Mine did, on every call, and the only thing keeping it from an infinite loop of updates was the under-the-covers check to see if the selection was the same. But what if there was a delay in the selection updates, and it caused a cycle between an old selection and the one that was just forced? Infinite loop...
I tried all kinds of things. First, I thought that there was a direct path between APF and update(), so I put some Boolean locks around the code calling APF to avoid stack overflows and stop the loop. But, even though it looks like it on the stack inspector, the selection changed events are detected in some sort of async loop instead inline with stack execution. Then I tried to make the code as clean as possible, but that didn't help. The piece of information I was missing? The very first call to update() after the constructor restored the previous selection filter w/o having to call APF. Support on the Power BI board, said to never call APF from update(), because it can cause an infinite loop, and testing showed that the previous selection was always pre-choosen when the report loads (as long as you store the selection under the property "general" when it changes, more on that later). So don't call APF from update().
But I really wanted to pick the first or last item by default. The change was to be sure to never call APF from update() more than once. I was already detecting the first call to update() after the constructor, then it was just a matter of:
- If it isn't the first call to update() don't call APF.
- If it's the first call to update() and only if the current selection isn't the one you want call APF.
|In this version, onChange() isn't called during a call to update()|