Skip to content

akshay5995/powerbi-report-component

Folders and files

NameName
Last commit message
Last commit date

Latest commit

74be69a · Jul 23, 2022
Jul 10, 2022
Jul 10, 2022
May 23, 2021
Apr 26, 2020
Sep 14, 2019
May 27, 2020
Sep 14, 2019
Sep 14, 2019
Jul 10, 2022
Jun 2, 2020
Jun 26, 2018
Jul 23, 2022
Jul 10, 2022
Jul 10, 2022
May 31, 2020
Jul 10, 2022

Repository files navigation

PowerBI Report Component

downloads license vulnerabilities bundlephobia

It's a minimalistic React component for embedding a Microsoft PowerBI report, dashboard or tile into your React application.

Installation

npm i powerbi-report-component

Usage for Report

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

Usage for Dashboard

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);
  }}
/>

Usage for Tile

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);
  }}
/>

Usage for ReportVisual

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);
  }}
/>

Like hooks ? You'll love this :)

useReport

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;

Passing in custom layout for useReport hook.

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);
}, []);

useBootstrap

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;

Report features and props you can pass into the component

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.

  1. Change Report Mode to View or Edit:
//mode can be "View" or "Edit"

changeMode = (mode) => this.report.switchMode(mode);
  1. Fullscreen
setFullscreen = () => this.report.fullscreen();
  1. Print Report
printReport = () => this.report.print();
  1. Set Filters
    //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;
    }
  }
  1. Get Filters
getFilter = () =>
  this.report
    .getFilters()
    .then(function (filters) {
      console.log(filters);
    })
    .catch(function (errors) {
      console.log(errors);
    });
  1. Remove Filters
removeFilters = () =>
  this.report.removeFilters().catch(function (errors) {
    console.log(errors);
  });
  1. Save edited report when in "Edit" mode

(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);
      }
    }
  }
  1. Show / Hide all visual headers:
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 features and props you can pass into the component

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:

  1. Fullscreen
setFullscreen = () => this.dashboard.fullscreen();

Tile features and props you can pass into the component

Tile Load

  onLoad={(data) => {
    console.log('Data from tile', data);
  }}

Tile Click

onClick = {(data) => {
    console.log('Data from tile', data);
}}

For playground visit:

http://akshay5995.github.io/powerbi-report-component

You can find out how to generate token for your report using Powershell from this video.

Alternatives

  1. https://github.com/microsoft/powerbi-client-react bundlephobia