# power-bi

{% hint style="info" %}
**Version compatibility**

* `power-bi` was introduced in version **4.34** of the JourneyApps Container.
* Support for Power BI dashboards was introduced in version 4.58.5 of the JourneyApps Container.
  {% endhint %}

{% hint style="success" %}
Also see the implementation guide on [Power BI Embedding](https://docs.journeyapps.com/reference/build/ui-components/all-ui-components/power-bi/guide-powerbi-embedding).
{% endhint %}

Use this component to embed Power BI reports and dashboards into applications.

### View XML Syntax

The component only requires the `config` attribute to work, while the `on-interaction` attribute is optional. The `$:` part is important for the `config` attribute because it requires a payload to be returned.

```xml
<power-bi
    config="$:getConfig()" 
    on-interaction="$:onInteraction(event)"
    height="$:getHeight()"
    show-scroll-button="true"
/>
```

| Field                    | Description                                                                                                                                                                                                                                          |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`                 | <p>A function for getting the authorization and configuration details from CloudCode / external source.<br><strong>Required</strong>: <code>true</code></p>                                                                                          |
| `on-interaction`         | <p>A function for when a user interacts with report visuals.<br><strong>Required</strong>: <code>false</code></p>                                                                                                                                    |
| `height`                 | <p>A function to provide the pixel height of the report instead of it being set to the view-port height.<br><strong>Default</strong>: View height<br><strong>Required</strong>: <code>false</code></p>                                               |
| `show-scroll-button`     | <p>Will display a :arrow-up-small: button in the top-right corner to scroll the view back to the top if the report scrolls slightly out of view.<br><strong>Default</strong>: <code>true</code><br><strong>Required</strong>: <code>false</code></p> |
| `show-fullscreen-button` | <p>Will display a button that allows the <code>power-bi</code> component use the entire screen.<br><strong>Default</strong>: <code>false</code><br><strong>Required</strong>: <code>false</code></p>                                                 |

### View JS

To assist with the bootstrapping of the `<power-bi>` component, make use of the `powerbi.config` helper to handle authentication and configuration. The purpose of this function is to provide a clean abstraction for configuring the Power BI component as well as to manage the caching of authorization tokens. **This function can be called as many times as required but will only request/perform authentication when needed**. For a more detailed list of options, see the the table below.

```javascript
function getConfig(){
    // Helper function to get Power BI credentials from CloudCode
    return powerbi.config({
      
        // The type of Power BI visualization to embed ("report" or "dashboard")
      	type: "<report|dashboard>",
      
        // The Power BI report ID which can be found on powerbi.com
        // Only required when embedding a report
        report: "<report_id_here>",
      
        // The Power BI dashboard ID which can be found on powerbi.com
        // Only required when embedding a dashboard
        dashboard: "<dashboard_id_here>",
      
        // The Power BI workspace ID which can be found on powerbi.com
        workspace: "<report_workspace_id_here>",
      
      	// How should the report be displayed
        layout: "vertical",
      
      	// Short-hand for CloudCode task (preferred) ...
      	cctask: '<cloud_code_task>',
      
      	// ... Or call it manually 
        authenticate: function(reportID, includeUrls){
            return CloudCode.callTask("<cloud_code_task>", {
              biReportId: reportID,
              biReportUrls: includeUrls
            });
        }
    })
}
```

### powerbi.config fields

<table><thead><tr><th width="280">Option Name</th><th>Description</th></tr></thead><tbody><tr><td><code>type</code></td><td>Type of visualization to embed - "report" or "dashboard".<br><strong>Required</strong>: <code>true</code></td></tr><tr><td><code>report</code></td><td>The ID of the Power BI Report.<br><strong>Required</strong>: <code>true</code> when "type" is "report"</td></tr><tr><td><code>dashboard</code></td><td>The ID of the Power BI Dashboard.<br><strong>Required</strong>: <code>true</code> when "type" is "dashboard"</td></tr><tr><td><code>workspace</code></td><td>The ID of the Power BI Workspace.<br><strong>Required</strong>: <code>true</code></td></tr><tr><td><code>layout</code></td><td>Can be one of "vertical" (mobile-portrait mode), "horizontal" (mobile-landscape mode) or "desktop" (desktop landscape mode).<br><strong>Required</strong>: <code>true</code><br><strong>Default</strong>: "vertical"</td></tr><tr><td><code>cctask</code></td><td>The name of the CloudCode task that will be used to handle authentication.<br><strong>Required</strong>: <code>true</code> when "authentication" is not present</td></tr><tr><td><code>authentication</code></td><td>A custom function that will be invoked when authentication for the specified report is required. See the table below for exact details on what this function should return.<br><strong>Required</strong>: <code>true</code> when "cctask" is not present</td></tr><tr><td><code>filterPaneEnabled</code></td><td>Will display a filter pane on the right of the <code>power-bi</code> component.<br><strong>Default</strong>: <code>false</code><br><strong>Required</strong>: <code>false</code></td></tr><tr><td><code>navContentPaneEnabled</code></td><td>Will display a navigation content pane at the bottom of the <code>power-bi</code> component.<br><strong>Default</strong>: <code>true</code><br><strong>Required</strong>: <code>false</code></td></tr><tr><td><code>settings</code></td><td><p>Introduced in Runtime version <strong>4.89.5</strong>.<br><br>Further customize the appearance and behavior of the report. <br><br>Note: Available settings are not maintained by JourneyApps. Use <a href="https://learn.microsoft.com/en-us/javascript/api/overview/powerbi/configure-report-settings#customize-settings">this as a reference</a> of which settings may be supported.</p><p><br>Settings added here will take precedence over any other config setting that affects the same setting e.g. Having both <code>config.navContentPaneEnabled = false</code>  and <code>config.settings.navContentPaneEnabled = true</code>  will evaluate <code>navContentPaneEnabled</code> as <code>true</code>.<br><br><strong>Required</strong>: <code>false</code></p></td></tr><tr><td></td><td></td></tr></tbody></table>

The `return` statement in both the `getConfig` function as well as the `authenticate` function are both important, and will not work if they are not present.

Here is an example of a recommended `getConfig()` function:

```javascript
function getConfig(){
    var mode = "desktop";
    if (journey.device.isPhone) {
        mode = journey.device.isPortrait ? "vertical" : "landscape";
    }
  
    return powerbi.config({
        type: "report",
        report: "1234-1234-1234-1234-1234",
        workspace: "1234-1234-1234-1234-1234",
        layout: mode,
        cctask: "get_authentication"
    })
}
```

### Writing a custom authenticate function

In the event where the helper tools cannot be used in CloudCode (or there is some other limitation or constraint), it is possible to provide a custom authenticate function. An example of the function you can use is provided below:

```javascript
function getConfig(){  
    return powerbi.config({
        type: "report",
        report: "1234-1234-1234-1234-1234",
        layout: "desktop",
        authenticate: function(reportID, includeUrls) {
          
          // Call a custom web task
          return CloudCode.callTask("custom-auth", {
            reportID: reportID,
            includeUrls: includeUrls
          });
        }
    })
}
```

The response of the authentication function should contain at minimum the following schema (which is a combination of two responses from the Power BI API):

```json
{
    // https://learn.microsoft.com/en-us/rest/api/power-bi/embed-token/dashboards-generate-token-in-group#embedtoken
    "embedToken": {
        "expiration": "{expiration}",
        "token": "{token}",
        "tokenId": "{tokenId}" 
    },
    // https://learn.microsoft.com/en-us/rest/api/power-bi/reports/get-reports
    "reportUrl": {
        "id": "string",
        "name": "string",
        "webUrl": "string",
        "embedUrl": "string",
        "datasetId": "string"
    }
}
```

### Dealing with interaction

When dealing with interaction, make use of the `event` parameter which contains focused information about what the end-user interacted with regarding the report itself.

```javascript
function onInteraction(event){
  console.log(event);  
}
```

The `event` object will take the form of:

```json
{
   // Represents the underlying data
   dataPoints: [
     {
        // Underlying data 
        identity: [
          {
            target: {
              table: "<data_set_name>",
              column: "<data_set_column>"
            },
            equals: "<some_value>"
          }
        ],
        // Front-facing data
        values: [
          {
            formattedValue: "<display_value>",
            target: {...}
          }
        ]
     }
   ],
  
   // The visual that was clicked
   visual: {
      name: "<name_of_visual>",
      type: "<type_of_visual>"
   },
  
   // Other data
   ...
}
```

In the above event payload, the `dataPoints` field represents the data from the report data-source that was clicked. This will contain fields such as the `table name`, as well as the `column name`, but will not contain keys and labels of the report itself. This means that, while the look and the display values of the report can change, the `dataPoints` will stay consistent as long as the data source is unchanged.

The `visual` field contains information about the graphic/control that was directly interacted with, including the type of control (eg. "slicer") and the name (eg. "slicer\_1234"). Use this field in conjunction with the data points to figure out what was clicked, as well as which data is being interacted with.
