Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Get Fabric Certified for FREE during Fabric Data Days. Don't miss your chance! Request now

Reply
YCbCr
Regular Visitor

Highlight resets when update() is called

Hi, I am having trouble synchronising selections between visuals.

 

The problem comes with making a selection in my visual after making a selection in another. 

Interacting solely with the other visual works fine, the update function in mine gets called and the selection gets synchronised by reading the highlight properties. The problem comes with then making a selection in my custom visual. If I select something, update() gets called immediately after containing no highlights at all. This then resets the selection. Only clicking again will the selection stay as update doesn't get called again. 

 

I'm not sure how to solve this. I can't find a way to ignore the problematic update or get the update to contain the selection that was just made, though I'm not sure either are on the right track. 

1 ACCEPTED SOLUTION
johnbasha33
Super User
Super User

Hi  , 

Highlight resets when update() is called after my visual selection
This is expected behavior in the custom visuals API, and it comes from how cross-highlighting vs. your own selection are represented:

When another visual drives the selection, the host can send a highlights array in your dataView (if your visual declares supportsHighlight: true). You read those highlights and render a partial emphasis. Microsoft Learn+1

When your visual drives the selection, the selection state is not echoed back via the highlights array. Instead, the host triggers an update() (often with a data query) and expects you to restore the selection using the Selection Manager (ISelectionManager). In other words: highlights are for cross-visual input, selection manager is for your visual’s own state. Microsoft Learn

So what you’re observing—first click selects, host fires update(), highlights are empty and your selection appears “lost” until a second click—usually means the visual is clearing its own selection because it only trusts highlights and isn’t restoring from the Selection Manager.


What to change
Declare highlight support (for cross-visual)
In capabilities.json, keep:
"dataViewMappings": [ ... ],
"supportsHighlight": true


Then use categorical.values[i].highlights only when present (that means another visual is selecting).

Own your selection state (for self-selection)

Use ISelectionManager to store and restore selected ISelectionIds.

On click in your visual:

await selectionManager.select(selectionId, multiSelect);
// Optionally set a guard flag here (see #3)

In update(options), don’t clear selection just because highlights is null/undefined. Instead:

If highlights exist → render cross-highlight.

Else if selectionManager.getSelectionIds().length > 0 → render your own selected points (re-apply the visual styling based on those IDs).

Else → render default (no selection).
Documentation for the Selection API: Microsoft Learn+1

Ignore the “echo” update caused by your own click (optional but helpful)
The host often re-queries and calls update() right after your select(). Add a short-lived guard flag so your next update() doesn’t wipe your in-memory selection while the new dataView is arriving.

Example pattern:

 

private skipNextUpdate = false;

onDataPointClick(selectionId) {
this.skipNextUpdate = true;
selectionManager.select(selectionId).then(() => {
// let the host call update()
});
}

public update(options: VisualUpdateOptions) {
if (this.skipNextUpdate) {
this.skipNextUpdate = false;
// Repaint using selectionManager.getSelectionIds()
this.renderFromSelectionManagerOrHighlights(options);
return;
}
this.renderFromSelectionManagerOrHighlights(options);
}

 

Branch logic on update type (optional)
You can check options.type (e.g., VisualUpdateType.Data, Resize, Style) to decide how aggressively to rebind or redraw. This won’t bring back highlights, but it helps reduce flicker and accidental clears.

 

Did I answer your question? Mark my post as a solution! Appreciate your Kudos !!

View solution in original post

2 REPLIES 2
v-sgandrathi
Community Support
Community Support

Hi @YCbCr,

Thank you @johnbasha33 for your response to the query.

Has your issue been resolved?
If the response provided by the community member addressed your query, could you please confirm? It helps us ensure that the solutions provided are effective and beneficial for everyone.

 

Thank you.
 

 

johnbasha33
Super User
Super User

Hi  , 

Highlight resets when update() is called after my visual selection
This is expected behavior in the custom visuals API, and it comes from how cross-highlighting vs. your own selection are represented:

When another visual drives the selection, the host can send a highlights array in your dataView (if your visual declares supportsHighlight: true). You read those highlights and render a partial emphasis. Microsoft Learn+1

When your visual drives the selection, the selection state is not echoed back via the highlights array. Instead, the host triggers an update() (often with a data query) and expects you to restore the selection using the Selection Manager (ISelectionManager). In other words: highlights are for cross-visual input, selection manager is for your visual’s own state. Microsoft Learn

So what you’re observing—first click selects, host fires update(), highlights are empty and your selection appears “lost” until a second click—usually means the visual is clearing its own selection because it only trusts highlights and isn’t restoring from the Selection Manager.


What to change
Declare highlight support (for cross-visual)
In capabilities.json, keep:
"dataViewMappings": [ ... ],
"supportsHighlight": true


Then use categorical.values[i].highlights only when present (that means another visual is selecting).

Own your selection state (for self-selection)

Use ISelectionManager to store and restore selected ISelectionIds.

On click in your visual:

await selectionManager.select(selectionId, multiSelect);
// Optionally set a guard flag here (see #3)

In update(options), don’t clear selection just because highlights is null/undefined. Instead:

If highlights exist → render cross-highlight.

Else if selectionManager.getSelectionIds().length > 0 → render your own selected points (re-apply the visual styling based on those IDs).

Else → render default (no selection).
Documentation for the Selection API: Microsoft Learn+1

Ignore the “echo” update caused by your own click (optional but helpful)
The host often re-queries and calls update() right after your select(). Add a short-lived guard flag so your next update() doesn’t wipe your in-memory selection while the new dataView is arriving.

Example pattern:

 

private skipNextUpdate = false;

onDataPointClick(selectionId) {
this.skipNextUpdate = true;
selectionManager.select(selectionId).then(() => {
// let the host call update()
});
}

public update(options: VisualUpdateOptions) {
if (this.skipNextUpdate) {
this.skipNextUpdate = false;
// Repaint using selectionManager.getSelectionIds()
this.renderFromSelectionManagerOrHighlights(options);
return;
}
this.renderFromSelectionManagerOrHighlights(options);
}

 

Branch logic on update type (optional)
You can check options.type (e.g., VisualUpdateType.Data, Resize, Style) to decide how aggressively to rebind or redraw. This won’t bring back highlights, but it helps reduce flicker and accidental clears.

 

Did I answer your question? Mark my post as a solution! Appreciate your Kudos !!

Helpful resources

Announcements
November Power BI Update Carousel

Power BI Monthly Update - November 2025

Check out the November 2025 Power BI update to learn about new features.

Fabric Data Days Carousel

Fabric Data Days

Advance your Data & AI career with 50 days of live learning, contests, hands-on challenges, study groups & certifications and more!

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.