Power BI is turning 10! Tune in for a special live episode on July 24 with behind-the-scenes stories, product evolution highlights, and a sneak peek at what’s in store for the future.
Save the dateEnhance your career with this limited time 50% discount on Fabric and Power BI exams. Ends August 31st. Request your voucher.
I am attempting to POC a Angular solution that will allow me to display two separate PowerBI reports, set filters on report 1 and transfer those same filter values to report 2. So far I have the solution to the point where I can display both reports in a component depending on whether I click a button called 'Report 1' and 'Report 2'. When I set the filters on report 1 and click the 'Report 2' button the filters from report 1 are synchronize with report 2 but the visualization of report 2 is not updated. However, when I log the new filters for report 2 I can see the new fitlers on the report 2 object but the visual will not update.
Here's the current reports.component.hmtl:
<h1>Reports</h1>
<div class="button-row">
<button mat-raised-button color="primary" (click)="toggleReport1()">Report 1</button>
<button mat-raised-button color="primary" (click)="toggleReport2()">Report 2</button>
</div>
<powerbi-report [hidden]="isShowReport1" [embedConfig]="reportConfig1" [cssClassName]="reportClass" [phasedEmbedding]="phasedEmbeddingFlag" [eventHandlers]="eventHandlersMapReport1">
</powerbi-report>
<powerbi-report id="report2-container" [hidden]="isShowReport2" [embedConfig]="reportConfig2" [cssClassName]="reportClass" [phasedEmbedding]="phasedEmbeddingFlag" [eventHandlers]="eventHandlersMapReport2">
</powerbi-report>
Here's the current reports.component.ts:
import { Component, OnInit, ViewChild } from '@angular/core';
import { IReportEmbedConfiguration, models, service, Embed, Report } from 'powerbi-client';
import { PowerBIReportEmbedComponent } from 'powerbi-client-angular';
@Component({
selector: 'app-reports',
templateUrl: './reports.component.html',
styleUrls: ['./reports.component.scss']
})
export class ReportsComponent implements OnInit {
@ViewChild(PowerBIReportEmbedComponent) reportObj!: PowerBIReportEmbedComponent;
isShowReport1 = true;
isShowReport2 = true;
report1Instance: Report | undefined;
report2Instance: Report | undefined;
showReport2Component = false;
filters: undefined;
ngOnInit() {
}
toggleReport1() {
this.isShowReport1 = false;
this.isShowReport2 = true; // Hide app-report2 component
}
toggleReport2() {
this.isShowReport1 = true;
this.isShowReport2 = false;
this.synchronizeFilters()
}
reportConfig1: IReportEmbedConfiguration = {
type: 'report',
embedUrl: this.report1EmbedUrl,
tokenType: models.TokenType.Embed,
accessToken: this.embed_token,
settings: {
panes: {
filters: {
expanded: true,
visible: true
}
},
background: models.BackgroundType.Transparent,
}
};
reportConfig2: IReportEmbedConfiguration = {
type: 'report',
embedUrl: this.report2EmbedUrl,
tokenType: models.TokenType.Embed,
accessToken: this.embed_token,
settings: {
panes: {
filters: {
expanded: true,
visible: true
}
},
background: models.BackgroundType.Transparent,
}
};
reportClass = 'reportContainer';
phasedEmbeddingFlag = false;
eventHandlersMapReport1 = new Map([
['loaded', () => {
const report = this.reportObj.getReport();
this.report1Instance = report;
report.setComponentTitle('Embedded report 1');
console.log('Report 1 has loaded');
},
],
['rendered', () => console.log('Report 1 has rendered')],
['error', (event?: service.ICustomEvent<any>) => {
if (event) {
console.error(event.detail);
}
},
],
['visualClicked', () => console.log('visual clicked')],
['pageChanged', (event) => console.log(event)],
]) as Map<string, (event?: service.ICustomEvent<any>, embeddedEntity?: Embed) => void | null>;
eventHandlersMapReport2 = new Map([
['loaded', () => {
const report = this.reportObj.getReport();
this.report2Instance = report;
report.setComponentTitle('Embedded report 2');
console.log('Report 2 has loaded');
},
],
['rendered', () => console.log('Report 2 has rendered')],
['error', (event?: service.ICustomEvent<any>) => {
if (event) {
console.error(event.detail);
}
},
],
['visualClicked', () => console.log('visual clicked')],
['pageChanged', (event) => console.log(event)],
]) as Map<string, (event?: service.ICustomEvent<any>, embeddedEntity?: Embed) => void | null>;
async getFiltersFromReport(reportInstance: Report): Promise<models.IFilter[]> {
const filters = await reportInstance.getFilters();
return filters;
}
async applyFiltersToReport(reportInstance: Report, filters: models.IFilter[]) {
try {
await reportInstance.updateFilters(models.FiltersOperations.ReplaceAll, filters);
console.log("All the report filters were replaced.");
} catch (error) {
console.error('Error applying filters and refreshing report:', error);
}
}
async synchronizeFilters() {
if (this.report1Instance && this.report2Instance) {
try {
const filters = await this.getFiltersFromReport(this.report1Instance);
console.log(filters);
await this.applyFiltersToReport(this.report2Instance, filters);
console.log('Filters applied to Report 2.');
const filters2 = await this.getFiltersFromReport(this.report2Instance);
console.log(filters2);
console.log('Filters synchronized between reports.');
} catch (error) {
console.error('Error synchronizing filters:', error);
}
}
}
}
Solved! Go to Solution.
Resolved: Resolution was ensuring the correct report instance was being used.
The way I was getting the report instance was not be differentiating between the two reports, which lead to an overlap. This was because I was using this.reportObj.getReport() for both reports. Instead, each powerbi-report should have its own ViewChild reference.
Modified the component with:
@ViewChild('report1') report1Obj: PowerBIReportEmbedComponent | undefined;
@ViewChild('report2') report2Obj: PowerBIReportEmbedComponent | undefined;
And then in the HTML:
<powerbi-report #report1 [hidden]="isShowReport1" [embedConfig]="reportConfig1" ...></powerbi-report>
<powerbi-report #report2 [hidden]="isShowReport2" [embedConfig]="reportConfig2" ...></powerbi-report>
Finally, in the event handlers:
['loaded', () => {
const report = this.report1Obj?.getReport();
if (report) {
this.report1Instance = report;
report.setComponentTitle('Embedded report 1');
console.log('Report 1 has loaded');
}
}],
...
['loaded', () => {
const report = this.report2Obj?.getReport();
if (report) {
this.report2Instance = report;
report.setComponentTitle('Embedded report 2');
console.log('Report 2 has loaded');
}
}],
Resolved: Resolution was ensuring the correct report instance was being used.
The way I was getting the report instance was not be differentiating between the two reports, which lead to an overlap. This was because I was using this.reportObj.getReport() for both reports. Instead, each powerbi-report should have its own ViewChild reference.
Modified the component with:
@ViewChild('report1') report1Obj: PowerBIReportEmbedComponent | undefined;
@ViewChild('report2') report2Obj: PowerBIReportEmbedComponent | undefined;
And then in the HTML:
<powerbi-report #report1 [hidden]="isShowReport1" [embedConfig]="reportConfig1" ...></powerbi-report>
<powerbi-report #report2 [hidden]="isShowReport2" [embedConfig]="reportConfig2" ...></powerbi-report>
Finally, in the event handlers:
['loaded', () => {
const report = this.report1Obj?.getReport();
if (report) {
this.report1Instance = report;
report.setComponentTitle('Embedded report 1');
console.log('Report 1 has loaded');
}
}],
...
['loaded', () => {
const report = this.report2Obj?.getReport();
if (report) {
this.report2Instance = report;
report.setComponentTitle('Embedded report 2');
console.log('Report 2 has loaded');
}
}],
Check out the July 2025 Power BI update to learn about new features.
User | Count |
---|---|
6 | |
6 | |
3 | |
2 | |
2 |