It's a minimalistic React component for embedding a Microsoft PowerBI report, dashboard or tile into your React application.
npm i powerbi-report-component
import React, {Component} from 'react';
import { Report } from 'powerbi-report-component';
class MyComponent extends Component {
constructor(props) {
super(props);
this.report = null; // to store the loaded report's object to perform operations like print, full screen etc..
}
...
handleDataSelected = (data) => {
// will be called when some chart or data element in your report clicked
}
handleReportLoad = (report) => {
// will be called when report loads:
// - scripts and data received from server, visuals are rendered on the browser
// - flickering Power BI logo stops appearing but report is not fully ready to be consumed
this.report = report; // get the report object from callback and store it.(optional)
}
handleReportRender = (report) => {
// will be called when report renders:
// - visuals finish rendering
// - report is fully visible and ready for consumption
this.report = report; // get the report object from callback and store it.(optional)
}
handlePageChange = (data) => {
// will be called when pages in your report changes
}
handleTileClicked = (data) => {
console.log('Data from tile', data);
}
render() {
const reportStyle = {
// style object for report component
};
const extraSettings = {
filterPaneEnabled: false, //true
navContentPaneEnabled: false, //true
hideErrors: false // Use this *only* when you want to override error experience i.e, use onError
// ... more custom settings
};
return (
<div className="root">
<Report
tokenType="Embed" // "Aad"
accessToken="" // accessToken goes here
embedUrl="" // embedUrl goes here
embedId="" // report or dashboard Id goes here
pageName="" // set as current page of the report. Name to be obtained from the original report URL
reportMode="View" // open report in a particular mode View/Edit/Create
datasetId={datasetId} // required for reportMode = "Create" and optional for dynamic databinding in `report` on `View` mode
groupId={groupId} // optional. Used when reportMode = "Create" and to chose the target workspace when the dataset is shared.
extraSettings={extraSettings}
permissions="All" // View, For "Edit" mode permissions should be "All"
style={reportStyle}
onLoad={this.handleReportLoad}
onRender={this.handleReportRender} // not allowed in "Create" mode
onSelectData={this.handleDataSelected}
onPageChange={this.handlePageChange}
onTileClicked={this.handleTileClicked}
onSave={this.handleReportSave} // works for "Edit" and "Create"
/>
</div>
);
}
}
Visit here for more details on creating reports with shared dataset
import { Dashboard } from 'powerbi-report-component';
// inside render
<Dashboard
tokenType={tokenType}
accessToken={accessToken}
embedUrl={embedUrl}
embedId={embedId}
style={style} // style object for dashboard component
pageView={pageView} // 'fitToWidth' (default) , 'oneColumn', 'actualSize'
onLoad={(dashboard) => {
console.log('Dashboard Loaded!');
this.dashboard = dashboard; // get the dashboard object from callback and store it.(optional)
}}
onTileClicked={(data) => {
console.log('Data from tile', data);
}}
/>
import { Tile } from 'powerbi-report-component';
// inside render
<Tile
tokenType={tokenType}
accessToken={accessToken}
embedUrl={embedUrl}
embedId={embedId}
dashboardId={dashboardId}
style={style} // style for tile component
onClick={(data) => {
console.log('Data from tile', data);
}}
onLoad={(data) => {
console.log('Tile loaded', data);
}}
/>
import { ReportVisual } from 'powerbi-report-component';
// inside render
<ReportVisual
tokenType={tokenType}
accessToken={accessToken}
embedUrl={embedUrl}
embedId={embedId}
pageName={pageName}
visualName={visualName}
style={style} // style for report visual component
onSelectData={(data) => {
console.log('Data from ReportVisual', data);
}}
onLoad={(reportVisual) => {
console.log('ReportVisual loaded', data);
}}
onRender={(reportVisual) => {
console.log('ReportVisual rendered', reportVisual);
}}
/>
Provides a more fine grained approach for embedding. (where you're in control)
import React, { useEffect, useRef } from 'react';
import { useReport } from 'powerbi-report-component';
const MyReport = ({ accessToken, embedUrl, embedId }) => {
const reportRef = useRef(null);
const [report, embed] = useReport();
const myReportConfig = {
embedType: 'report',
tokenType: 'Embed',
accessToken: accessToken,
embedUrl: embedUrl,
embedId: embedId,
reportMode: "View", // "Edit"
permissions: "View", // "All" (when using "Edit" mode)
extraSettings: {
filterPaneEnabled: false,
navContentPaneEnabled: false,
},
};
// important
useEffect(() => {
// call inside useEffect so the we have the reportRef (reference available)
embed(reportRef, myReportConfig);
}, []);
const handleClick = () => {
// you can use "report" from useReport like
if (report) report.print();
};
return (
<div className="report-container">
<div className="report" ref={reportRef} />
<button onClick={handleClick}>Print my report</button>
</div>
);
};
export default MyReport;
Example is taken from powerbi js wiki: Custom-Layout.
import { models } from 'powerbi-client'; // Import from the dependency
// Example layout config
const layoutSettings = {
layoutType: models.LayoutType.Custom,
customLayout: {
pageSize: {
type: models.PageSizeType.Custom,
width: 1600,
height: 1200,
},
displayOption: models.DisplayOption.ActualSize,
pagesLayout: {
ReportSection1: {
defaultLayout: {
displayState: {
mode: models.VisualContainerDisplayMode.Hidden,
},
},
visualsLayout: {
VisualContainer1: {
x: 1,
y: 1,
z: 1,
width: 400,
height: 300,
displayState: {
mode: models.VisualContainerDisplayMode.Visible,
},
},
VisualContainer2: {
displayState: {
mode: models.VisualContainerDisplayMode.Visible,
},
},
},
},
},
},
};
// Create your config
const myReportConfig = {
embedType: 'report',
tokenType: 'Embed',
accessToken: accessToken,
embedUrl: embedUrl,
embedId: embedId,
extraSettings: {
filterPaneEnabled: false,
navContentPaneEnabled: false,
...layoutSettings, // layout config
},
};
// Inside your component
useEffect(() => {
embed(reportRef, myReportConfig);
}, []);
Provided performance gains on loading in an async way
import React, { useEffect, useRef } from 'react';
import { useBootstrap } from 'powerbi-report-component';
// Your configuration from server
const simulateAjaxCall = () => new Promise(function(resolve) {
setTimeout(resolve.bind(null, {
accessToken: "accessToken",
embedUrl: "embedUrl",
embedId: "embedId",
reportMode: "View", // "Edit"
permissions: "View", // "All" (when using "Edit" mode)
}), 3000)
});
const MyReport = ({ accessToken, embedUrl, embedId }) => {
const reportRef = useRef(null);
const [report, bootstrap, embed] = useBootstrap();
const initialReportConfig = {
embedType: 'report',
tokenType: 'Embed',
extraSettings: {
filterPaneEnabled: false,
navContentPaneEnabled: false,
},
};
const getMyConfigurationFromServer = () => {
simulateAjaxCall().then(data => {
// Embed the report once your configuration is received
embed(reportRef, {...initialReportConfig, ...data});
});
}
// important
useEffect(() => {
// call inside useEffect so the we have the reportRef (reference available)
bootstrap(reportRef, initialReportConfig);
}, []);
return (
<div className="report-container">
<div className="report" ref={reportRef} />
<button onClick={getMyConfiguraionFromServer}>Get config from AJAX call</button>
</div>
);
};
export default MyReport;
Inside your component where you're using { Report } component.
Constructor:
...
constructor(props) {
super(props);
this.report = null; //used to store value of returned report object
}
....
Callback passed to the onLoad or onRender prop
handleReportLoad = (report) => {
this.report = report; // get the report object from callback and store it.
}
handleReportRender = (report) => {
this.report = report; // get the report object from callback and store it.
}
...
using the this.report to perform operations
...
setFullscreen = () => {
if(this.report) this.report.fullscreen();
}
printReport = () => {
if(this.report) this.report.print();
}
...
//Inside render
<button onClick={this.setFullscreen}>Fullscreen</button>
<button onClick={this.printReport}>Print</button>
...
For Report Level Filters:
/*
Example filter object used in microsoft's demo page:
const filter = {
$schema: "http://powerbi.com/product/schema#basic",
target: {
table: "Store",
column: "Chain"
},
operator: "In",
values: ["Lindseys"]
};
*/
...
setFilter = (filter) => this.report.setFilters([filter]).catch(function (errors) {
console.log(errors);
});
getFilter = () => this.report.getFilters().then(function (filters) {
console.log(filters);
}).catch(function (errors) {
console.log(errors);
});
removeFilters = () => this.report.removeFilters()
.catch(function (errors) {
console.log(errors);
});
...
Report Page Change
onPageChange={(data) =>
console.log(`Page name :{data.newPage.displayName}`)
}
Report Load
onLoad={(report) => {
console.log('Report Loaded!');
this.report = report;
}
}
onSave={(data) => {
console.log('Report Saved! Event data: '+data);
}
}
Report Render
onRender={(report) => {
console.log('Report Rendered!');
this.report = report;
}
}
Report Button Clicked
onButtonClicked={(data) => {
console.log(`Button ${data.title} of type ${data.type} Clicked!`);
}
}
Report Command Triggered
onCommandTriggered={(extensionCommand) => {
console.log('Extension Command Triggered!');
}
}
Report Data Element Clicked
onSelectData={(data) =>
console.log(`You clicked on chart: ${data.visual.title}`);
}
Report Handle Errors
onError={(data) =>
console.log(`Error: ${data}`);
}
Use ‘report’ object returned to parent component or from useReport
for:
Note: you wouldn't use this
if you're using report
from useReport
hook.
//mode can be "View" or "Edit"
changeMode = (mode) => this.report.switchMode(mode);
setFullscreen = () => this.report.fullscreen();
printReport = () => this.report.print();
//example filter from microsoft's demo page
const filter = {
$schema: "http://powerbi.com/product/schema#basic",
target: {
table: "Store",
column: "Chain"
},
operator: "In",
values: ["Lindseys"]
};
// using event handlers
setFilter = (filter) => this.report.setFilters([filter]).catch(function (errors) {
console.log(errors);
});
// during onload
onLoad = (report) => {
report.setFilters([filter]).catch(function (errors) {
console.log(errors);
});
this.report = report;
}
}
getFilter = () =>
this.report
.getFilters()
.then(function (filters) {
console.log(filters);
})
.catch(function (errors) {
console.log(errors);
});
removeFilters = () =>
this.report.removeFilters().catch(function (errors) {
console.log(errors);
});
(note: you need to have enough permissions to save the report)
async saveReport() {
if (this.report) {
try{
await this.report.save();
} catch (err) {
console.log("Error saving report", err);
}
}
}
toggleAllVisualHeaders = (bool) => {
const newSettings = {
visualSettings: {
visualHeaders: [
{
settings: {
visible: bool, // boolean variable
},
},
],
},
};
this.report
.updateSettings(newSettings)
.then(function () {
console.log('Visual header toggle successful.');
})
.catch(function (errors) {
console.log(errors);
});
};
Dashboard Load
onLoad={(dashboard) => {
console.log('Report Loaded!');
this.dashboard = dashboard;
}
}
Dashboard Tile Click
onTileClicked = {(data) => {
console.log('Data from tile', data);
}}
Use dashboard object returned to parent component for:
setFullscreen = () => this.dashboard.fullscreen();
Tile Load
onLoad={(data) => {
console.log('Data from tile', data);
}}
Tile Click
onClick = {(data) => {
console.log('Data from tile', data);
}}
For playground visit:
You can find out how to generate token for your report using Powershell from this video.