Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Power BI Client
https://github.com/microsoft/powerbi-javascript
Admin
Power BI Client is a JavaScript library for embedding Power BI reports, dashboards, and visuals into
...
Tokens:
22,035
Snippets:
197
Trust Score:
9.9
Update:
5 days ago
Context
Skills
Chat
Benchmark
89.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Power BI Client Power BI Client (`powerbi-client`) is a Microsoft-authored JavaScript/TypeScript library for embedding Power BI reports, dashboards, tiles, visuals, and Q&A components directly into web applications. It abstracts the iframe-based embedding mechanism and the underlying postMessage communication layer, exposing a clean object model that lets developers programmatically interact with every embedded artifact — navigating pages, applying filters, managing bookmarks, controlling visual layout, and handling user-interaction events — all without navigating away from the host application. The library is structured around a central `Service` singleton that manages all active embeds on a page. Each call to `service.embed()`, `service.load()`, or `service.bootstrap()` returns a typed embed instance (`Report`, `Dashboard`, `Tile`, `Visual`, or `Qna`). These instances expose async methods that communicate with the embedded iframe via postMessage and return Promises, making them straightforward to `await` or chain. Reports expose a rich hierarchy — `Report → Page → VisualDescriptor` — at each level of which filters, settings, and layout can be independently controlled. --- ## Service — Initialize and embed a report `powerbi.embed(element, config)` is the primary entry point for all embed types. It creates an iframe in the target DOM element and returns the appropriate embed instance based on `config.type`. ```typescript import * as pbi from 'powerbi-client'; // The global `powerbi` service instance is created automatically when the script loads. // For module environments, create one explicitly: const service = new pbi.service.Service( pbi.factories.hpmFactory, pbi.factories.wpmpFactory, pbi.factories.routerFactory ); const embedContainer = document.getElementById('reportContainer'); const reportConfig: pbi.IReportEmbedConfiguration = { type: 'report', id: '5dac7a4a-4452-46b3-99f6-a25915e0fe55', embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=5dac7a4a-4452-46b3-99f6-a25915e0fe55&groupId=me', accessToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5...', tokenType: pbi.models.TokenType.Embed, settings: { navContentPaneEnabled: true, filterPaneEnabled: false, localeSettings: { language: 'en', formatLocale: 'en-US' } } }; const report = service.embed(embedContainer, reportConfig) as pbi.Report; // The iframe is created immediately; `report` is ready to use after the 'loaded' event fires. report.on('loaded', () => console.log('Report loaded')); report.on('error', (event) => console.error('Embed error:', event.detail)); ``` --- ## Service.bootstrap / Service.load / Report.render — Phased embedding `bootstrap()` pre-warms the iframe without an access token; `load()` prepares the report without rendering; `render()` finalises display. Together they allow performance-optimised page transitions. ```typescript // Step 1 – bootstrap early (no token required) const bootstrapConfig: pbi.IBootstrapEmbedConfiguration = { type: 'report', hostname: 'https://app.powerbi.com' }; const report = service.bootstrap(embedContainer, bootstrapConfig) as pbi.Report; // Step 2 – later, when the token is available, load without rendering const fullConfig: pbi.IReportEmbedConfiguration = { type: 'report', id: '5dac7a4a-4452-46b3-99f6-a25915e0fe55', embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=5dac7a4a-4452-46b3-99f6-a25915e0fe55', accessToken: 'eyJ0eXAiOiJKV1Qi...', tokenType: pbi.models.TokenType.Embed }; const phasedReport = service.load(embedContainer, fullConfig) as pbi.Report; // Step 3 – render when the user navigates to the page phasedReport.on('loaded', async () => { await phasedReport.render(); console.log('Report rendered'); }); ``` --- ## Service.preload — Warm-start embed endpoints `service.preload()` creates a hidden iframe pointing at the Power BI embed host, so the browser pre-establishes connections before the user triggers the actual embed, reducing perceived load time. ```typescript const iframe = service.preload({ type: 'report', embedUrl: 'https://app.powerbi.com/reportEmbed' }); iframe.addEventListener('preloaded', () => { console.log('Endpoint pre-warmed; subsequent embed() calls will be faster.'); }); ``` --- ## Service.get / Service.find / Service.reset — Manage active embeds `get()` retrieves the embed instance associated with a DOM element; `find()` searches by unique ID; `reset()` destroys an embed and removes its iframe. ```typescript // Retrieve existing embed from DOM element const existingReport = service.get(embedContainer) as pbi.Report; // Find by unique ID (useful across components) const reportById = service.find('my-unique-report-id') as pbi.Report; // Destroy embed and clean up service.reset(embedContainer); console.log('Embed removed from container'); ``` --- ## Service.createReport — Create a new report from a dataset `createReport()` opens the Power BI report-creation experience inside an iframe, targeting an existing dataset. ```typescript const createConfig: pbi.IReportCreateConfiguration = { type: 'create', datasetId: 'ab8a88f4-fef2-4a82-8e52-0a0f9b2e2130', embedUrl: 'https://app.powerbi.com/reportEmbed', accessToken: 'eyJ0eXAiOiJKV1Qi...', tokenType: pbi.models.TokenType.Embed, settings: { navContentPaneEnabled: false } }; const createEmbed = service.createReport(embedContainer, createConfig); createEmbed.on('saved', (event) => { console.log('Report saved:', event.detail); }); createEmbed.on('saveAsTriggered', (event) => { console.log('Save-As triggered:', event.detail); }); ``` --- ## Embed.on / Embed.off — Event handling All embed types inherit `on()` and `off()` from the `Embed` base class for subscribing and unsubscribing to lifecycle and interaction events. ```typescript const report = service.embed(embedContainer, reportConfig) as pbi.Report; // Subscribe const pageChangedHandler = (event: pbi.service.ICustomEvent<any>) => { console.log('Active page changed to:', event.detail.newPage.displayName); }; report.on('pageChanged', pageChangedHandler); report.on('dataSelected', (event) => { console.log('Data selected:', event.detail); }); report.on('commandTriggered', (event) => { console.log('Custom command triggered:', event.detail.command); }); // Unsubscribe a specific handler report.off('pageChanged', pageChangedHandler); // Unsubscribe all handlers for an event report.off('dataSelected'); ``` Available report events: `loaded`, `rendered`, `saved`, `saveAsTriggered`, `error`, `dataSelected`, `buttonClicked`, `pageChanged`, `commandTriggered`, `swipeStart`, `swipeEnd`, `bookmarkApplied`, `dataHyperlinkClicked`, `visualRendered`, `visualClicked`, `selectionChanged`, `renderingStarted`. --- ## Embed.setAccessToken — Refresh an expired access token `setAccessToken()` pushes a new token to the embedded iframe without re-creating the embed, enabling seamless token refresh for long-lived sessions. ```typescript async function refreshToken(report: pbi.Report, getNewToken: () => Promise<string>) { try { const newToken = await getNewToken(); await report.setAccessToken(newToken); console.log('Token refreshed successfully'); } catch (error) { console.error('Token refresh failed:', error); } } ``` --- ## Embed.save / Embed.saveAs — Save a report `save()` persists changes to the existing report; `saveAs()` creates a copy under a new name in the specified workspace. ```typescript const report = service.embed(embedContainer, reportConfig) as pbi.Report; // Save in place await report.save(); // Save as a copy await report.saveAs({ name: 'Q3 Sales Report – Copy', targetWorkspaceId: 'workspace-guid-here' }); ``` --- ## Embed.reload — Reset a report to its default state `reload()` re-sends the original load configuration, clearing all applied filters and returning to the first page. ```typescript const resetButton = document.getElementById('resetBtn'); resetButton.addEventListener('click', async () => { await report.reload(); console.log('Report reset to default state'); }); ``` --- ## Embed.fullscreen / Embed.exitFullscreen — Fullscreen mode `fullscreen()` and `exitFullscreen()` control the browser fullscreen state for the embed iframe. ```typescript document.getElementById('fullscreenBtn').addEventListener('click', () => { report.fullscreen(); }); document.getElementById('exitFullscreenBtn').addEventListener('click', () => { report.exitFullscreen(); }); ``` --- ## Embed.getCorrelationId — Retrieve session correlation ID `getCorrelationId()` returns the current embed session's correlation ID, useful for diagnostics and support. ```typescript const correlationId = await report.getCorrelationId(); console.log('Correlation ID for support:', correlationId); // e.g. "d9a01428-fc47-4b4b-8893-7c285f421f41" ``` --- ## Report.getPages / Report.getActivePage / Report.setPage — Page navigation `getPages()` retrieves all pages; `getActivePage()` returns the currently visible page; `setPage()` navigates to a page by its internal name. ```typescript const report = service.embed(embedContainer, reportConfig) as pbi.Report; report.on('loaded', async () => { // List all pages const pages = await report.getPages(); pages.forEach(p => console.log(`${p.name}: ${p.displayName} (active: ${p.isActive})`)); // e.g. "ReportSection1: Overview (active: true)" // e.g. "ReportSection2: Sales Details (active: false)" // Get the active page const activePage = await report.getActivePage(); console.log('Current page:', activePage.displayName); // Navigate to a specific page await report.setPage('ReportSection2'); }); ``` --- ## Report.addPage / Report.deletePage / Report.renamePage — Page management These methods add, remove, or rename pages in edit mode. ```typescript // Switch to edit mode first await report.switchMode(pbi.models.ViewMode.Edit); // Add a new page const newPage = await report.addPage('New Analysis'); console.log('Created page:', newPage.name, newPage.displayName); // Rename an existing page await report.renamePage('ReportSection3', 'Renamed Page'); // Delete a page by its internal name await report.deletePage('ReportSection3'); ``` --- ## Report.getFilters / Report.setFilters / Report.updateFilters / Report.removeFilters — Report-level filters These methods read and write filters applied at the whole-report level. ```typescript import { models } from 'powerbi-client'; // Get current report filters const currentFilters = await report.getFilters(); console.log('Active filters:', currentFilters); // Replace all report-level filters const basicFilter: models.IBasicFilter = { $schema: 'http://powerbi.com/product/schema#basic', target: { table: 'Sales', column: 'Region' }, operator: 'In', values: ['West', 'East'], filterType: models.FilterType.Basic }; await report.setFilters([basicFilter]); // Add a filter without replacing existing ones await report.updateFilters(models.FiltersOperations.Add, [basicFilter]); // Remove all report-level filters await report.removeFilters(); ``` --- ## Report.updateSettings — Update display settings at runtime `updateSettings()` updates pane visibility, zoom, locale, custom layout, and extension commands without reloading the report. ```typescript await report.updateSettings({ navContentPaneEnabled: false, filterPaneEnabled: false, zoomLevel: 1.5, panes: { bookmarks: { visible: true, expanded: false }, fields: { expanded: false }, filters: { expanded: false, visible: false }, pageNavigation: { visible: true, position: pbi.models.PageNavigationPosition.Left }, selection: { visible: false }, syncSlicers: { visible: false }, visualizations: { expanded: false } } }); ``` --- ## Report.applyTheme / Report.resetTheme / Report.getTheme — Theme management These methods allow runtime control of the visual theme applied to a report. ```typescript // Apply a custom theme await report.applyTheme({ name: 'CorporateTheme', dataColors: ['#118DFF', '#12239E', '#E66C37', '#6B007B'], background: '#FFFFFF', foreground: '#252423', tableAccent: '#118DFF' }); // Get the current theme const currentTheme = await report.getTheme(); console.log('Current theme:', currentTheme.name); // Reset to the report's default theme await report.resetTheme(); ``` --- ## Report.refresh — Refresh data sources `refresh()` triggers a data refresh in the embedded report, re-querying underlying data sources. ```typescript const refreshButton = document.getElementById('refreshData'); refreshButton.addEventListener('click', async () => { try { await report.refresh(); console.log('Data refreshed successfully'); } catch (err) { console.error('Refresh failed:', err); } }); ``` --- ## Report.switchMode — Toggle view/edit mode `switchMode()` toggles between View mode (read-only) and Edit mode (authoring). ```typescript // Switch to edit mode await report.switchMode(pbi.models.ViewMode.Edit); // Make some edits, then switch back to view mode await report.switchMode(pbi.models.ViewMode.View); ``` --- ## Report.switchLayout — Switch between desktop and mobile layouts `switchLayout()` changes the report's layout type (Master, MobilePortrait, MobileLandscape, Custom). ```typescript // Switch to mobile portrait layout (must match the initial embed layout type) await report.switchLayout(pbi.models.LayoutType.MobilePortrait); // Switch back to desktop layout await report.switchLayout(pbi.models.LayoutType.Master); ``` --- ## Report.resizeVisual / Report.moveVisual / Report.setVisualDisplayState — Visual layout control These methods manipulate individual visual positions, sizes, and visibility in custom layout mode. ```typescript // Show only one visual (hide others via display state) await report.setVisualDisplayState( 'ReportSection1', 'BarChart1', pbi.models.VisualContainerDisplayMode.Visible ); // Move a visual to a new position (x, y in pixels) await report.moveVisual('ReportSection1', 'BarChart1', 100, 200); // Resize a visual await report.resizeVisual('ReportSection1', 'BarChart1', 400, 300); // Resize the active page canvas await report.resizeActivePage(pbi.models.PageSizeType.Custom, 1280, 720); ``` --- ## Report.addContextMenuCommand / Report.addOptionsMenuCommand — Extend visual menus These methods inject custom commands into visual context menus and options menus, enabling integration with host-app logic. ```typescript report.on('commandTriggered', (event) => { if (event.detail.command === 'drillToDetail') { console.log('Drill-to-detail triggered on visual:', event.detail.visual?.name); // Open a detail panel in your app } }); // Add a context menu command for all bar chart visuals await report.addContextMenuCommand( 'drillToDetail', // commandName 'Drill to Detail', // commandTitle 'Drill to Detail', // contextMenuTitle pbi.models.MenuLocation.Top, undefined, // visualName (undefined = all visuals) 'barChart' // visualType ); // Add an options menu command await report.addOptionsMenuCommand( 'exportCustom', 'Export to App', 'Export to App', pbi.models.MenuLocation.Bottom ); // Remove a context menu command await report.removeContextMenuCommand('drillToDetail', 'Drill to Detail'); ``` --- ## Report.savePersistentFilters / Report.resetPersistentFilters / Report.arePersistentFiltersApplied — Persistent filters These methods save and restore a user's personal filter/slicer state across sessions. ```typescript // Check if user has any saved state const hasUserState = await report.arePersistentFiltersApplied(); console.log('User has saved filters:', hasUserState); // Save the user's current filter selections await report.savePersistentFilters(); console.log('User state saved'); // Reset to the report's default filter state await report.resetPersistentFilters(); console.log('User state cleared'); ``` --- ## Report.isSaved / Report.print / Report.closeAllOverlays / Report.clearSelectedVisuals — Utility methods ```typescript // Check if the report has unsaved changes const saved = await report.isSaved(); if (!saved) { await report.save(); } // Print the active page await report.print(); // Close any open tooltips or context menus await report.closeAllOverlays(); // Clear all visual selections (pass true to also clear pop-out visuals) await report.clearSelectedVisuals(false); ``` --- ## Report.getZoom / Report.setZoom — Zoom control ```typescript // Get current zoom level (1.0 = 100%) const zoom = await report.getZoom(); console.log('Current zoom:', zoom); // e.g. 1.0 // Set zoom to 75% await report.setZoom(0.75); ``` --- ## Page.setActive / Page.setDisplayName / Page.delete — Page-level operations `Page` instances are obtained from `report.getPages()` or `report.getActivePage()` and expose operations scoped to a single page. ```typescript const pages = await report.getPages(); const targetPage = pages.find(p => p.displayName === 'Sales Details'); if (targetPage) { // Navigate to this page await targetPage.setActive(); // Rename the page await targetPage.setDisplayName('Revenue Details'); // Delete the page await targetPage.delete(); } ``` --- ## Page.getFilters / Page.setFilters / Page.updateFilters / Page.removeFilters — Page-level filters Filters can be read and written at the page level independently of report-level filters. ```typescript const activePage = await report.getActivePage(); const regionFilter: pbi.models.IBasicFilter = { $schema: 'http://powerbi.com/product/schema#basic', target: { table: 'Geography', column: 'Country' }, operator: 'In', values: ['United States', 'Canada'], filterType: pbi.models.FilterType.Basic }; // Set page-level filters (replaces existing ones) await activePage.setFilters([regionFilter]); // Add without replacing await activePage.updateFilters(pbi.models.FiltersOperations.Add, [regionFilter]); // Remove all page-level filters await activePage.removeFilters(); ``` --- ## Page.getVisuals / Page.getVisualByName / Page.getSlicers — Visual discovery `getVisuals()` returns all `VisualDescriptor` instances on a page; `getSlicers()` filters to slicer type only. ```typescript const activePage = await report.getActivePage(); // Get all visuals const visuals = await activePage.getVisuals(); visuals.forEach(v => console.log(`${v.name} (${v.type}): ${v.title}`)); // Get a specific visual by name const barChart = await activePage.getVisualByName('BarChart1'); console.log('Found visual:', barChart.title, 'at position', barChart.layout); // Get only slicer visuals const slicers = await activePage.getSlicers(); console.log('Slicers on page:', slicers.map(s => s.title)); ``` --- ## Page.hasLayout / Page.resizePage — Page layout ```typescript const activePage = await report.getActivePage(); // Check if the page has a mobile portrait layout defined const hasMobile = await activePage.hasLayout(pbi.models.LayoutType.MobilePortrait); console.log('Has mobile layout:', hasMobile); // Resize the active page to a custom size await activePage.resizePage(pbi.models.PageSizeType.Custom, 1920, 1080); ``` --- ## VisualDescriptor.getFilters / setFilters / updateFilters / removeFilters — Visual-level filters `VisualDescriptor` exposes filter methods scoped to a single visual. ```typescript const activePage = await report.getActivePage(); const visual = await activePage.getVisualByName('SalesBarChart'); // Get visual-level filters const visualFilters = await visual.getFilters(); // Set a visual-level filter const categoryFilter: pbi.models.IBasicFilter = { $schema: 'http://powerbi.com/product/schema#basic', target: { table: 'Product', column: 'Category' }, operator: 'In', values: ['Bikes', 'Accessories'], filterType: pbi.models.FilterType.Basic }; await visual.setFilters([categoryFilter]); // Add without replacing existing await visual.updateFilters(pbi.models.FiltersOperations.Add, [categoryFilter]); // Remove all visual-level filters await visual.removeFilters(); ``` --- ## VisualDescriptor.exportData — Export visual data `exportData()` exports up to 30,000 rows of the visual's underlying data. ```typescript const visual = await activePage.getVisualByName('SalesTable'); // Export summarized data (default) const summarized = await visual.exportData(pbi.models.ExportDataType.Summarized); console.log('CSV data (summarized):', summarized.data); // Export underlying (raw) data const raw = await visual.exportData(pbi.models.ExportDataType.Underlying, 1000); console.log('CSV data (raw, 1000 rows):', raw.data); ``` --- ## VisualDescriptor.setSlicerState / getSlicerState — Slicer control `setSlicerState()` and `getSlicerState()` programmatically control slicer visual selections. ```typescript const slicers = await activePage.getSlicers(); const regionSlicer = slicers.find(s => s.title === 'Region Slicer'); // Get current slicer state const currentState = await regionSlicer.getSlicerState(); console.log('Current slicer filters:', currentState.filters); // Set slicer to specific selections await regionSlicer.setSlicerState({ filters: [{ $schema: 'http://powerbi.com/product/schema#basic', target: { table: 'Geography', column: 'Region' }, operator: 'In', values: ['West'], filterType: pbi.models.FilterType.Basic }] }); ``` --- ## VisualDescriptor.sortBy — Sort a visual `sortBy()` changes the sort field and direction of a visual. ```typescript const visual = await activePage.getVisualByName('SalesBarChart'); await visual.sortBy({ orderBy: [{ table: 'Sales', measure: 'Total Revenue', direction: pbi.models.SortDirection.Descending }] }); ``` --- ## VisualDescriptor.clone — Clone a visual `clone()` duplicates a visual onto the same page, optionally at a specified position and size. ```typescript const visual = await activePage.getVisualByName('SalesBarChart'); const cloneResponse = await visual.clone({ position: { x: 500, y: 100 }, size: { width: 400, height: 300 } }); console.log('Cloned visual name:', cloneResponse.visual?.name); ``` --- ## VisualDescriptor.getSmartNarrativeInsights / Page.getSmartNarrativeInsights — AI insights `getSmartNarrativeInsights()` retrieves auto-generated narrative insights for a visual or full page. ```typescript // Insights for a single visual const visual = await activePage.getVisualByName('RevenueTrend'); const visualInsights = await visual.getSmartNarrativeInsights(); console.log('Visual insights:', visualInsights); // Insights for the full page const pageInsights = await activePage.getSmartNarrativeInsights(); console.log('Page insights:', pageInsights); ``` --- ## BookmarksManager — Manage report bookmarks `report.bookmarksManager` exposes APIs to list, apply, capture, and play report bookmarks. ```typescript const bm = report.bookmarksManager; // List all defined bookmarks const bookmarks = await bm.getBookmarks(); bookmarks.forEach(b => console.log(b.name, b.displayName)); // e.g. "Bookmark1 – Q1 Overview" // Apply a bookmark by name await bm.apply('Bookmark1'); // Capture current state as a new bookmark const captured = await bm.capture({ personalizeVisuals: true, allPages: false }); console.log('Captured state:', captured.state); // Apply a previously captured state (base64 string) await bm.applyState(captured.state); // Enter bookmark presentation mode await bm.play(pbi.models.BookmarksPlayMode.Presentation); // Exit bookmark presentation mode await bm.play(pbi.models.BookmarksPlayMode.Off); ``` --- ## Visual embed — Embed a single visual `type: 'visual'` renders only one visual from a report, suppressing all other page content. ```typescript const visualConfig: pbi.IVisualEmbedConfiguration = { type: 'visual', id: '5dac7a4a-4452-46b3-99f6-a25915e0fe55', // report ID embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=5dac7a4a-4452-46b3-99f6-a25915e0fe55', accessToken: 'eyJ0eXAiOiJKV1Qi...', tokenType: pbi.models.TokenType.Embed, pageName: 'ReportSection1', visualName: 'BarChart1' }; const visualEmbed = service.embed(embedContainer, visualConfig) as pbi.Visual; // Get descriptor of the embedded visual visualEmbed.on('loaded', async () => { const descriptor = await visualEmbed.getVisualDescriptor(); console.log('Embedded visual:', descriptor.title, descriptor.type); }); // Apply a filter scoped to this visual await visualEmbed.setFilters([{ $schema: 'http://powerbi.com/product/schema#basic', target: { table: 'Sales', column: 'Year' }, operator: 'In', values: [2024], filterType: pbi.models.FilterType.Basic }]); ``` --- ## Dashboard embed — Embed a dashboard `type: 'dashboard'` embeds a full Power BI dashboard with tile-click event support. ```typescript const dashboardConfig: pbi.IDashboardEmbedConfiguration = { type: 'dashboard', id: 'abc12345-ab12-ab12-ab12-abc123456789', embedUrl: 'https://app.powerbi.com/dashboardEmbed?dashboardId=abc12345-ab12-ab12-ab12-abc123456789', accessToken: 'eyJ0eXAiOiJKV1Qi...', tokenType: pbi.models.TokenType.Embed, pageView: 'fitToWidth' // 'fitToWidth' | 'oneColumn' | 'actualSize' }; const dashboard = service.embed(embedContainer, dashboardConfig) as pbi.Dashboard; dashboard.on('tileClicked', (event) => { console.log('Tile clicked:', event.detail); }); dashboard.on('error', (event) => { console.error('Dashboard error:', event.detail); }); ``` --- ## BasicFilterBuilder — Build basic filters fluently `BasicFilterBuilder` provides a fluent API for constructing `BasicFilter` objects without manually composing the JSON schema. ```typescript import { BasicFilterBuilder } from 'powerbi-client'; const filter = new BasicFilterBuilder() .withTable('Sales') .withColumn('Region') .in(['West', 'East', 'North']) .build(); // Use with requireSingleSelection const singleSelectFilter = new BasicFilterBuilder() .withTable('Product') .withColumn('Category') .in(['Bikes']) .requireSingleSelection(true) .build(); await report.setFilters([filter, singleSelectFilter]); // NotIn operator const excludeFilter = new BasicFilterBuilder() .withTable('Date') .withColumn('Year') .notIn([2020, 2021]) .build(); // All values (clear filter) const allFilter = new BasicFilterBuilder() .withTable('Sales') .withColumn('Region') .all() .build(); ``` --- ## AdvancedFilterBuilder — Build advanced filters fluently `AdvancedFilterBuilder` constructs multi-condition `AdvancedFilter` objects with AND/OR logical operators. ```typescript import { AdvancedFilterBuilder } from 'powerbi-client'; // Filter: City contains "Wash" AND City contains "Park" const andFilter = new AdvancedFilterBuilder() .withTable('Geography') .withColumn('City') .and() .addCondition('Contains', 'Wash') .addCondition('Contains', 'Park') .build(); // Filter: Revenue > 1000000 OR Revenue is blank const orFilter = new AdvancedFilterBuilder() .withTable('Sales') .withMeasure('Total Revenue') .or() .addCondition('GreaterThan', 1000000) .addCondition('IsBlank') .build(); await report.setFilters([andFilter]); await activePage.setFilters([orFilter]); ``` --- ## Service.register — Register custom embed components `service.register()` extends the service with custom embed types, enabling embedding of non-built-in Power BI component types. ```typescript service.register( 'customVisual', // Factory function that creates the embed component (svc, element, config, phasedRender, isBootstrap) => { return new pbi.Report(svc, element, config, phasedRender, isBootstrap); }, // Router event URL patterns (must include :uniqueId and :eventName) ['/customVisuals/:uniqueId/events/:eventName'] ); // Now embed using the custom type const customEmbed = service.embed(embedContainer, { type: 'customVisual', embedUrl: 'https://app.powerbi.com/reportEmbed?...', accessToken: 'eyJ0...', tokenType: pbi.models.TokenType.Embed }); ``` --- ## Auto-embed via HTML attributes Setting `autoEmbedOnContentLoaded: true` in the service config enables declarative embedding directly from HTML data attributes, with no JavaScript embed call needed. ```typescript // Configure service for auto-embed const autoService = new pbi.service.Service( pbi.factories.hpmFactory, pbi.factories.wpmpFactory, pbi.factories.routerFactory, { autoEmbedOnContentLoaded: true } ); ``` ```html <!-- Report will be auto-embedded when DOMContentLoaded fires --> <div powerbi-type="report" powerbi-embed-url="https://app.powerbi.com/reportEmbed?reportId=5dac7a4a..." powerbi-access-token="eyJ0eXAiOiJKV1Qi..." powerbi-report-id="5dac7a4a-4452-46b3-99f6-a25915e0fe55" powerbi-settings-filter-pane-enabled="false" powerbi-settings-nav-content-pane-enabled="true" style="height:600px;"> </div> ``` --- ## Summary Power BI Client is the standard solution for integrating Power BI analytics into any web application. The most prevalent use case is building internal portals or SaaS products where tenants need to view reports scoped to their own data, typically implemented with Embed tokens generated server-side and pushed to the browser. Developers initialise the `Service`, call `service.embed()` with the embed URL, token, and configuration, then listen to the `loaded` event before exercising the report's API — navigating pages, applying filters to pre-select data for the current user, reading visual data via `exportData()`, and responding to selection events to drive side-panel content or cross-application navigation. A second common pattern is embedded analytics with authoring capabilities: developers use `switchMode(ViewMode.Edit)` to let power users customise reports in-place, `addContextMenuCommand()` to inject custom workflows into visual context menus (for example, "Open in CRM"), bookmark management to save and restore named views per user, and persistent filters to remember each user's last filter state. The phased embedding API (`bootstrap → load → render`) is recommended in multi-report dashboards to parallelise iframe warm-up and minimise total time-to-visible. Token refresh via `setAccessToken()` handles sessions that outlive the initial embed token lifetime, and `service.preload()` can be used during idle time to pre-warm endpoints before the user navigates to a report page.