Forum Discussion
ViDuong
8 months agoFrequent Visitor
VisualUpdate doesn't trigger in custom visual when switching from reading to edit mode
I am having the following problem: Previously, I used dataViewMapping as TABLE and it worked fine. But after I used dataViewMapping MATRIX instead of TABLE, it did not trigger the update function w...
Ahmed-Elfeel
8 months agoSuper User
Hi ViDuong,
When switching between reading mode and edit mode Power BI doesn't always trigger the update() method for matrix based visuals this happens because:
TABLE mapping creates a new dataView when mode changes
- MATRIX mapping often reuses the same dataView object
- Power BI optimizes by not calling update() if it thinks the data hasnt changed
First Approach:Force Update Using View Mode Change Events
- Add view mode change detection in your visual:
export class YourVisual implements IVisual {
private host: IVisualHost;
private currentViewMode: ViewMode;
constructor(options: VisualConstructorOptions) {
this.host = options.host;
// Listen for view mode changes
this.host.viewModeChanged.subscribe((viewMode: ViewMode) => {
this.currentViewMode = viewMode;
// Force a re-render when view mode changes
this.handleViewModeChange();
});
}
public update(options: VisualUpdateOptions) {
this.currentViewMode = options.viewMode;
// ... your existing update logic
}
private handleViewModeChange() {
// Manually trigger UI updates for edit mode
if (this.currentViewMode === ViewMode.Edit) {
this.renderEditModeUI();
} else {
this.renderReadModeUI();
}
}
}
Second Approach:Use EnumerateObjects to Force Data Refresh
- Modify your capabilities to include objects enumeration:
{
"objects": {
"general": {
"properties": {
"viewModeToggle": {
"type": {
"bool": true
}
}
}
}
}
}- Then in your update method:
public update(options: VisualUpdateOptions) {
this.countRender++;
this.viewMode = options.viewMode;
this.events.renderingStarted(options);
// Force enumerate objects to trigger updates
if (options.viewMode === ViewMode.Edit) {
this.host.persistProperties({
merge: [{
objectName: "general",
properties: {
viewModeToggle: this.viewMode === ViewMode.Edit
},
selector: null
}]
});
}
const dataView = options.dataViews?.[0];
// ... rest of your code
}
Third Approach:Check for Mode Specific Changes in Update
- Enhance your update method to detect mode changes:
public update(options: VisualUpdateOptions) {
this.countRender++;
// Check if view mode actually changed
const viewModeChanged = this.viewMode !== options.viewMode;
this.viewMode = options.viewMode;
this.events.renderingStarted(options);
const dataView = options.dataViews?.[0];
if (!dataView?.matrix) {
this.dataOriginal = undefined;
if (this.countRender > 3) this.clearNodePositions();
this.countRender = 0;
this.renderUI();
return;
}
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(
VisualSettingsModel,
dataView
);
// Always render on mode change, even if data appears unchanged
if (viewModeChanged) {
this.renderUI();
return;
}
// ... your existing data processing logic
}
Bonus Approach:Use Update Types
- Leverage the type property in VisualUpdateOptions:
public update(options: VisualUpdateOptions) {
// Check the update type
if (options.type === VisualUpdateType.ViewModeChange) {
// Force complete re-render
this.forceFullRender = true;
}
// ... your existing code
if (this.forceFullRender || !dataView?.matrix) {
this.forceFullRender = false;
this.renderUI();
return;
}
}
if this post helps, then I would appreciate a thumbs up and mark it as the solution to help the other members find it more quickly.