Power Bi Developer Visuals
Power Bi Developer Visuals
Get started
b GET STARTED
g TUTORIAL
p CONCEPT
p CONCEPT
REFERENCE
REFERENCE
i
Samples of Power BI visuals
Git repository
What are custom visuals in Power BI and
where can I get them?
Article • 11/02/2023
To remove a Power BI visual from the visualization pane, right-click it and select unpin.
To restore the default Power BI visuals in the visualization pane, select the ellipsis and
then select Restore default visuals.
AppSource Power BI visuals
You can find many more Power BI visuals in AppSource . AppSource is the place to find
apps, add-ins, and extensions for your Microsoft software. It connects millions of people
who use products such as Microsoft 365, Azure, Dynamics 365, Cortana, and Power BI, to
solutions that help them work more efficiently and with more insight than before.
Microsoft and community members develop Power BI visuals for public benefit, and
publish them to the AppSource. Microsoft tests and approves these Power BI visuals for
functionality and quality. You can download these visuals and add them to your Power
BI reports.
7 Note
By using Power BI visuals created with our SDK, you may be importing data
from, or sending data to, a third party or other service outside of your Power
BI tenant’s geographic area, compliance boundary, or national/regional cloud
instance.
Once Power BI visuals from AppSource are imported, they may be updated
automatically without any additional notice.
Free visuals that you can download and use without additional costs. These visuals
are labeled as Free.
Licensed visuals managed from the Microsoft 365 admin center. These visuals are
available in a limited capacity for free with the option to purchase more features.
Transactability happens in AppSource by clicking on the Buy now button.
Visuals that you can download with basic functionality for free, but have additional
features available for pay. These visuals have the additional purchase may be
required label. You can often get a free trial period to test out the full functionality
of the visual before paying for it. Transactability and license management for these
visuals happen outside of Microsoft platforms.
Once you select the visual, select the Plans + Pricing tab to see the plan for that visual.
Pricing information is also shown on the left pane.
Select Add to download the visual. If a free trial period is offered, it will start when you
download the visual.
After you purchase the licenses for the visual in AppSource with a credit card, you need
to assign them to yourself or others in the Microsoft 365 admin center.
For more information on how to assign licenses see Licensing and transactability
enforcement.
To view the list of certified Power BI visuals, go to AppSource . To submit your own
visual for certification, see Certified Power BI visuals.
Organizational store
Power BI admins can approve and deploy Power BI custom visuals for their organization.
Report authors can easily discover, update, and use these Power BI visuals. Admins can
easily manage these visuals with actions such as updating versions, disabling and
enabling Power BI visuals.
To access the organizational store, in the Visualization pane select the ellipsis, then
select Get more visuals.
When the Power BI visuals window appears, select the My organization tab.
Power BI visuals come in .pbiviz file packages that include code for rendering the data
served to them. Anyone can create a custom visual and package it as a .pbiviz file that
can then be imported into a Power BI report.
To import a Power BI visual from a file, see Import a visual file from your local computer
into Power BI.
If you're a web developer and want to create your own visual and add it to AppSource,
you can learn how to develop a Power BI visual and publish a custom visual to
AppSource.
2 Warning
A Power BI custom visual could contain code with security or privacy risks. Make
sure you trust the author and source before importing it to your report.
For some examples of Power BI custom visuals available for downloading on github, see
Examples of Power BI visuals.
Related content
Develop a Power BI circle card visual
Power BI visuals project structure
Guidelines for Power BI visuals
Examples of Power BI visuals
Feedback
Was this page helpful? Yes No
Power BI comes with core visuals readily available on the visualization pane. You can also
import visuals from Microsoft AppSource or Power BI.
If none of these visuals meet your specific needs, you can create your own custom
Power BI visual to be used by you, your organization, or the entire Power BI community.
To import a Power BI visual from a file, see Import a visual file from your local computer
into Power BI.
If you're a web developer interested in creating your own visual and adding it to
AppSource, you can learn how to develop a Power BI circle card visual and publish a
Power BI visual to AppSource.
Related content
Develop a Power BI circle card visual
Power BI visuals project structure
Guidelines for Power BI visuals
Feedback
Was this page helpful? Yes No
In this tutorial, you develop a Power BI visual named circle card that displays a formatted
measure value inside a circle. The circle card visual supports customization of fill color
and outline thickness.
7 Note
For the full source code of this visual, see circle card Power BI visual .
Prerequisites
Before you start developing your Power BI visual, verify that you have everything listed
in this section.
A Power BI Pro or Premium Per User (PPU) account. If you don't have one, sign up
for a free trial .
This tutorial uses the US Sales Analysis report. You can download this report and
upload it to Power BI service, or use your own report. If you need more information
about Power BI service, and uploading files, refer to the Get started creating in the
Power BI service tutorial.
Create a development project
In this section, you create a project for the circle card visual.
7 Note
In this tutorial, Visual Studio Code (VS Code) is used for developing the Power BI
visual.
1. Open a new terminal in VS Code and navigate to the folder you want to create
your project in.
PowerShell
3. Open the CircleCard folder in the VS Code explorer. (File > Open Folder).
For a detailed explanation of the function of each of these files, see Power BI visual
project structure.
4. Check the terminal window and confirm that you're in the circleCard directory.
Install the Power BI visual tools dependencies .
PowerShell
npm install
Tip
To see which dependencies have been installed in your visual, check the
package.json file.
5. Start the circle card visual.
PowerShell
pbiviz start
) Important
Don't close the PowerShell window until the end of the tutorial. To stop the
visual from running, enter Ctrl + C and if prompted to terminate the batch
job, enter Y and then Enter .
You can also use your own report to test the visual.
7 Note
Before you continue, verify that you enabled the visuals developer settings.
2. Select Edit.
3. Create a new page for testing, by clicking on the New page button at the bottom
of the Power BI service interface.
4. From the Visualizations pane, select the Developer Visual.
This visual represents the custom visual that you're running on your computer. It's
only available when the custom visual debugging setting is enabled.
7 Note
If the visual displays a connection error message, open a new tab in your
browser, navigate to https://localhost:8080/assets , and authorize your
browser to use this address.
6. While the new visual is selected, go to the Data pane, expand Sales, and select
Quantity.
7. To test how the visual is responding, resize it and notice that the Update count
value increments every time you resize the visual.
Tip
To improve readability, it's recommended that you format the document every time
you copy code snippets into your project. Right-click anywhere in VS code, and
select Format Document (or enter Alt + Shift + F ).
1. In VS Code, in the Explorer pane, expand the src folder, and select the file visual.ts.
2. Remove all the code under the MIT License comment.
) Important
Notice the comments at the top of the visual.ts file. Permission to use the
Power BI visual packages is granted free of charge under the terms of the
Massachusetts Institute of Technology (MIT) License. As part of the
agreement, you must leave the comments at the top of the file.
3. Import the libraries and modules needed, and define the type selection for the d3
library:
TypeScript
"use strict";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions =
powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions =
powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import DataView = powerbi.DataView;
import IVisualHost = powerbi.extensibility.IVisualHost;
import * as d3 from "d3";
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
7 Note
If the D3 JavaScript library wasn't installed as part of your setup, install it now.
From PowerShell, run npm i d3@latest --save
4. Below the imports, create an empty visual class. The visual class implements the
IVisual interface where all visuals begin:
TypeScript
For information about what goes into the visual class, see Visual API. In the next
three steps, we define this class.
TypeScript
Notice that some of these private methods use the Selection type.
6. Define the circle and text elements in the constructor method. This method is
called when the visual is instantiated. The D3 Scalable Vector Graphics (SVG)
enable creating three shapes: a circle, and two text elements:
TypeScript
constructor(options: VisualConstructorOptions) {
this.svg = d3.select(options.element)
.append('svg')
.classed('circleCard', true);
this.container = this.svg.append("g")
.classed('container', true);
this.circle = this.container.append("circle")
.classed('circle', true);
this.textValue = this.container.append("text")
.classed("textValue", true);
this.textLabel = this.container.append("text")
.classed("textLabel", true);
}
7. Define the width and height in the update method. This method is called every
time there's a change in the data or host environment, such as a new value or
resizing.
TypeScript
/*
* Power BI Visual CLI
*
* Copyright (c) Microsoft Corporation
* All rights reserved.
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
copy
* of this software and associated documentation files (the ""Software""),
to deal
* in the Software without restriction, including without limitation the
rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
"use strict";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions =
powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions =
powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import DataView = powerbi.DataView;
import IVisualHost = powerbi.extensibility.IVisualHost;
import * as d3 from "d3";
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
constructor(options: VisualConstructorOptions) {
this.svg = d3.select(options.element)
.append('svg')
.classed('circleCard', true);
this.container = this.svg.append("g")
.classed('container', true);
this.circle = this.container.append("circle")
.classed('circle', true);
this.textValue = this.container.append("text")
.classed("textValue", true);
this.textLabel = this.container.append("text")
.classed("textLabel", true);
}
1. In the PowerShell window where you started the visual, enter Ctrl + C . If
prompted to terminate the batch job, enter Y and then Enter .
PowerShell
pbiviz start
1. In Power BI service, open the Power BI US Sales Analysis report. If you're using a
different report to develop the circle card visual, navigate to that report.
2. Drag a value into the Measure box and make sure that the visual is shaped as a
circle.
If the visual isn't displaying anything, from the Fields pane, drag the Quantity field
into the developer visual.
Notice that the circle and text scale to fit the dimensions of the visual. The update
method is called when you resize the visual, and as a result the visual elements get
rescaled.
1. Navigate to the Power BI US Sales Analysis report (or to the project that has your
circle card visual).
2. Select the circle card visual.
Define the dataRoles array with a single data role of the type measure. This data
role is called measure, and is displayed as Measure. It allows passing either a
measure field, or a summed up field.
{
"displayName": "Measure",
"name": "measure",
"kind": "Measure"
}
Define a field called measure in the dataViewMappings array. This field can be
passed to the data role.
JSON
{
"conditions": [
{ "measure": { "max": 1 } }
],
"single": {
"role": "measure"
}
}
TypeScript
{
"dataRoles": [
{
"displayName": "Measure",
"name": "measure",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{ "measure": { "max": 1 } }
],
"single": {
"role": "measure"
}
}
],
"privileges": []
}
1. In Power BI service, open the Power BI US Sales Analysis report. If you're using a
different report to develop the circle card visual, navigate to that report.
2. Notice that the circle card visual can now be configured with a field titled Measure.
You can drag and drop elements from the Data pane into the Measure field.
7 Note
The visual project does not yet include data binding logic.
5. Expand metadata, then the columns array, and review the format and
displayName values.
6. To toggle back to the visual, in the toolbar floating above the visual, select Show
Dataview.
Add the following statement as the first statement. The statement assigns
dataView to a variable for easy access, and declares the variable to reference
the dataView object.
TypeScript
TypeScript
.text(<string>dataView.single.value)
Replace .text("Label") with this line of code:
TypeScript
.text(dataView.metadata.columns[0].displayName)
The visual now displays the name and value of the selected data field.
You created a working Power BI visual. You can add formatting options to it, or you can
package it as is for immediate use.
Related content
Add formatting options to the circle card visual
Power BI visuals project structure
Learn how to debug a Power BI visual you created
Feedback
Was this page helpful? Yes No
When you create a visual, you can add options for customizing its properties. Some of
the items that can be to customized formatted include:
Title
Background
Border
Shadow
Colors
Prerequisite
This tutorial explains how to add common formatting properties to a visual. We'll use
the Circle card visual as an example. We'll add the ability to change the color and
thickness of the circle. If you don't have the Circle card project folder that you created in
that tutorial, redo the tutorial before continuing.
PowerShell
pbiviz start
You should see general formatting options, but not any visual formatting options.
3. In Visual Studio Code, open the capabilities.json file.
JSON
"objects": {},
5. Save the capabilities.json file.
7 Note
If you don't see the formatting options change, select Reload Custom Visual.
7. Set the Title option to Off. Notice that the visual no longer displays the measure
name at the top-left corner.
Adding custom formatting options
Now let's add new group called color for configuring the circle color and thickness of
the circle's outline.
2. In Visual Studio Code, in the capabilities.json file, insert the following JSON
fragment into the object labeled objects.
JSON
"circle": {
"properties": {
"circleColor": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"circleThickness": {
"type": {
"numeric": true
}
}
}
}
This JSON fragment describes a group called circle, which consists of two variables
- circleColor and circleThickness.
4. In the Explorer pane, go to the src folder, and then select settings.ts. This file
represents the settings for the starter visual.
5. In the settings.ts file, replace the import lines and two classes with the following
code.
TypeScript
This module defines the two classes. The CircleSettings class defines two
properties with names that match the objects defined in the capabilities.json file
(circleColor and circleThickness) and sets default values. The VisualSettings class
defines the circle object according to the properties described in the
capabilities.json file.
TypeScript
TypeScript
private visualSettings: VisualSettings;
private formattingSettingsService: FormattingSettingsService;
This property stores a reference to the VisualSettings object, describing the visual
settings.
9. In the Visual class, insert the following as the first line of the constructor:
TypeScript
10. In the Visual class, add the following method after the update method.
TypeScript
This function gets called on every formatting pane render. It allows you to select
which of the objects and properties you want to expose to the users in the
property pane.
11. In the update method, after the declaration of the radius variable, add the
following code.
TypeScript
this.visualSettings =
this.formattingSettingsService.populateFormattingSettingsModel(VisualSe
ttings, options.dataViews[0]);
this.visualSettings.circle.circleThickness.value = Math.max(0,
this.visualSettings.circle.circleThickness.value);
this.visualSettings.circle.circleThickness.value = Math.min(10,
this.visualSettings.circle.circleThickness.value);
This code retrieves the format options. It adjusts any value passed into the
circleThickness property, and converts it to a number between zero and 10.
12. In the circle element, modify the values passed to the fill style and stroke-width
style as follows:
TypeScript
.style("fill", this.visualSettings.circle.circleColor.value.value)
TypeScript
.style("stroke-width",
this.visualSettings.circle.circleThickness.value)
PowerShell
pbiviz start
15. In Power BI, in the toolbar floating above the visual, select Toggle Auto Reload.
Modify the thickness option to a value less than zero, and a value higher than 10. Then
notice the visual updates the value to a tolerable minimum or maximum.
Debugging
For tips about debugging your custom visual, see the debugging guide.
When your visual is ready, follow the directions in Package a Power BI visual and then, if
you want, share it with others so they can import and enjoy it.
Related content
Create a Power BI bar chart visual
Learn how to debug a Power BI visual you created
Power BI visuals project structure
Tutorial: Build a bar chart
Article • 05/13/2024
This tutorial shows you how to develop a Power BI visual that displays data in the form
of a simple bar chart. This visual supports a minimal amount of customization. Other
pages of this documentation explain how to add further customization like context
menus, tool-tips, and more.
A Power BI Pro or Premium Per User (PPU) account. If you don't have one, sign up
for a free trial .
This tutorial uses the US Sales Analysis report. You can download this report and
upload it to Power BI service, or use your own report. If you need more information
about Power BI service, and uploading files, refer to the Get started creating in the
Power BI service tutorial.
7 Note
If the D3 JavaScript library wasn't installed as part of your setup, install it now. From
PowerShell, run npm i d3@latest --save
Creating a bar chart visual involves the following steps:
1. Open PowerShell and navigate to the folder you want to create your project
in.
PowerShell
You should now have a folder called BarChart containing the visual's files.
TypeScript
"files": [
"src/barChart.ts"
]
The tsconfig.json "files" object points to the file where the main class of the
visual is located.
You should now have a new folder for your visual with the following files and folders:
For a detailed explanation of the function of each of these files, see Power BI visual
project structure.
The two files we focus on in this tutorial are the capabilities.json file, which describes the
visual to the host, and the src/barchart.ts file, which contains the visual's API.
Define capabilities
The capabilities.json file is where we bind data to the host. We describe the kind of data
fields it accepts and what features the visual should have.
Define data roles
Variables are defined and bound in the dataRoles section of the capabilities file. We
want our bar chart to accept two types of variables:
In Visual Studio Code, in the capabilities.json file, confirm that the following JSON
fragment appears in the object labeled "dataRoles".
JSON
"dataRoles": [
{
"displayName": "Category Data",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure Data",
"name": "measure",
"kind": "Measure"
}
],
Replace the content of the "dataViewMappings" object with the following code:
JSON
"dataViewMappings": [
{
"conditions": [
{
"category": {
"max": 1
},
"measure": {
"max": 1
}
}
],
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
}
}
],
The above code creates the "conditions" that each data-role object can hold only one
field at a time. Notice that we use the data-role's internal name to refer to each field.
It also sets the categorical data mapping so that each field is mapped to the correct
variable.
For more information on objects and how they work, see Objects.
The following objects are optional. Add them if you want to go through the optional
sections of this tutorial to add colors and render the X-axis.
Replace the content of the "objects" section with the following code:
JSON
"objects": {
"enableAxis": {
"properties": {
"show": {
"type": {
"bool": true
}
},
"fill": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
},
"colorSelector": {
"properties": {
"fill": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
}
},
Your final capabilities file should look like the one in this example .
Visual API
All visuals start with a class that implements the IVisual interface. The src/visual.ts file is
the default file that contains this class.
In this tutorial, we call our IVisual file barChart.ts. Download the file and save it to
the /src folder, if you didn't do so already. In this section, we go through this file in detail
and describe the various sections.
Imports
The first section of the file imports the modules that are needed for this visual. Notice
that in addition to the Power BI visual modules, we also import the d3 library .
TypeScript
import {
BaseType,
select as d3Select,
Selection as d3Selection
} from "d3-selection";
import {
ScaleBand,
ScaleLinear,
scaleBand,
scaleLinear
} from "d3-scale";
import "./../style/visual.less";
// powerbi.visuals
import DataViewCategoryColumn = powerbi.DataViewCategoryColumn;
import Fill = powerbi.Fill;
import ISandboxExtendedColorPalette =
powerbi.extensibility.ISandboxExtendedColorPalette;
import ISelectionId = powerbi.visuals.ISelectionId;
import IVisual = powerbi.extensibility.IVisual;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import PrimitiveValue = powerbi.PrimitiveValue;
import VisualUpdateOptions =
powerbi.extensibility.visual.VisualUpdateOptions;
import VisualConstructorOptions =
powerbi.extensibility.visual.VisualConstructorOptions;
import DataViewObjectPropertyIdentifier =
powerbi.DataViewObjectPropertyIdentifier;
Interfaces
Next, we define the visual interfaces. The following interface is used to describe our bar
chart visual:
BarChartDataPoint
TypeScript
/**
* Interface for BarChart data points.
*
* @interface
* @property {PrimitiveValue} value - Data value for point.
* @property {string} category - Corresponding category of data
value.
* @property {string} color - Color corresponding to data point.
* @property {string} strokeColor - Stroke color for data point
column.
* @property {number} strokeWidth - Stroke width for data point
column.
* @property {ISelectionId} selectionId - Id assigned to data point for
cross filtering
* and visual interaction.
*/
interface BarChartDataPoint {
value: PrimitiveValue;
category: string;
color: string;
strokeColor: string;
strokeWidth: number;
selectionId: ISelectionId;
}
Visual transform
Now that the data structure is defined, we need to map data onto it using the
createSelectorDataPoints function. This function receives data from the data view and
transforms it to a format the visual can use. In this case, it returns the
BarChartDataPoint[] interface described in the previous section.
The DataView contains the data to be visualized. This data can be in different forms,
such as categorical or tabular. To build a categorical visual like a bar chart, use the
categorical property on the DataView .
TypeScript
/**
* Function that converts queried data into a viewmodel that will be used by
the visual.
*
* @function
* @param {VisualUpdateOptions} options - Contains references to the size of
the container
* and the dataView which contains
all the data
* the visual had queried.
* @param {IVisualHost} host - Contains references to the host
which contains services
*/
function createSelectorDataPoints(options: VisualUpdateOptions, host:
IVisualHost): BarChartDataPoint[] {
const barChartDataPoints: BarChartDataPoint[] = []
const dataViews = options.dataViews;
if (!dataViews
|| !dataViews[0]
|| !dataViews[0].categorical
|| !dataViews[0].categorical.categories
|| !dataViews[0].categorical.categories[0].source
|| !dataViews[0].categorical.values
) {
return barChartDataPoints;
}
barChartDataPoints.push({
color,
strokeColor,
strokeWidth,
selectionId,
value: dataValue.values[i],
category: `${category.values[i]}`,
});
}
return barChartDataPoints;
}
7 Note
The next few functions in the barChart.ts file deal with color and creating the X axis.
Those are optional and are discussed further down in this tutorial. This tutorial will
continue from the IVisual function.
TypeScript
static Config = {
xScalePadding: 0.1,
solidOpacity: 1,
transparentOpacity: 1,
margins: {
top: 0,
right: 0,
bottom: 25,
left: 30,
},
xAxisFontMultiplier: 0.04,
};
}
TypeScript
/**
* Creates instance of BarChart. This method is only called once.
*
* @constructor
* @param {VisualConstructorOptions} options - Contains references to
the element that will
* contain the visual and a
reference to the host
* which contains services.
*/
constructor(options: VisualConstructorOptions) {
this.host = options.host;
//Creating the formatting settings service.
const localizationManager = this.host.createLocalizationManager();
this.formattingSettingsService = new
FormattingSettingsService(localizationManager);
this.svg = d3Select(options.element)
.append('svg')
.classed('barChart', true);
this.barContainer = this.svg
.append('g')
.classed('barContainer', true);
this.xAxis = this.svg
.append('g')
.classed('xAxis', true);
}
Scaling
We need to scale the visual so that the number of bars and current values fit into the
defined width and height limits of the visual. This is similar to the update method in the
Circle card tutorial.
To calculate the scale, we use the scaleLinear and scaleBand methods that were
imported earlier from the d3-scale library.
The options.dataViews[0].categorical.values[0].maxLocal value holds the largest value
of all current data points. This value is used to determine the height of the y axis. The
scaling for the width of the x axis is determined by the number of categories bound to
the visual in the barchartdatapoint interface.
For cases where the X axis is rendered, this visual also handles word breaks in case there
isn't enough room to write out the entire name on the X axis.
TypeScript
/**
* Updates the state of the visual. Every sequential databinding and
resize will call update.
*
* @function
* @param {VisualUpdateOptions} options - Contains references to the
size of the container
* and the dataView which
contains all the data
* the visual had queried.
*/
public update(options: VisualUpdateOptions) {
this.formattingSettings =
this.formattingSettingsService.populateFormattingSettingsModel(BarChartSetti
ngsModel, options.dataViews?.[0]);
this.barDataPoints = createSelectorDataPoints(options, this.host);
this.formattingSettings.populateColorSelector(this.barDataPoints);
this.svg
.attr("width", width)
.attr("height", height);
if (this.formattingSettings.enableAxis.show.value) {
const margins = BarChart.Config.margins;
height -= margins.bottom;
}
this.xAxis
.style("font-size", Math.min(height, width) *
BarChart.Config.xAxisFontMultiplier)
.style("fill",
this.formattingSettings.enableAxis.fill.value.value);
const yScale: ScaleLinear<number, number> = scaleLinear()
.domain([0,
<number>options.dataViews[0].categorical.values[0].maxLocal])
.range([height, 0]);
this.barSelection = this.barContainer
.selectAll('.bar')
.data(this.barDataPoints);
barSelectionMerged.classed('bar', true);
barSelectionMerged
.attr("width", xScale.bandwidth())
.attr("height", (dataPoint: BarChartDataPoint) => height -
yScale(<number>dataPoint.value))
.attr("y", (dataPoint: BarChartDataPoint) =>
yScale(<number>dataPoint.value))
.attr("x", (dataPoint: BarChartDataPoint) =>
xScale(dataPoint.category))
.style("fill", (dataPoint: BarChartDataPoint) =>
dataPoint.color)
.style("stroke", (dataPoint: BarChartDataPoint) =>
dataPoint.strokeColor)
.style("stroke-width", (dataPoint: BarChartDataPoint) =>
`${dataPoint.strokeWidth}px`);
this.barSelection
.exit()
.remove();
}
To build a formatting model, the developer should be familiar with all its components.
Check out the components of the format pane in Format Pane. Check out
getFormattingModel API of the FormattingModel utils in the formatting model utils
repository .
Download the file and save it to the /src folder. Declare formatting properties and
their values in a formatting settings class:
TypeScript
/**
* Enable Axis Formatting Card
*/
class EnableAxisCardSettings extends Card {
show = new ToggleSwitch({
name: "show",
displayName: undefined,
value: false,
});
/**
* Color Selector Formatting Card
*/
class ColorSelectorCardSettings extends Card {
name: string = "colorSelector";
displayName: string = "Data Colors";
/**
* BarChart formatting settings model class
*/
export class BarChartSettingsModel extends Model {
// Create formatting settings model formatting cards
enableAxis = new EnableAxisCardSettings();
colorSelector = new ColorSelectorCardSettings();
cards: Card[] = [this.enableAxis, this.colorSelector];
/**
* populate colorSelector object categories formatting properties
* @param dataPoints
*/
populateColorSelector(dataPoints: BarChartDataPoint[]) {
const slices: Slice[] = this.colorSelector.slices;
if (dataPoints) {
dataPoints.forEach(dataPoint => {
slices.push(new ColorPicker({
name: "fill",
displayName: dataPoint.category,
value: { value: dataPoint.color },
selector: dataPoint.selectionId.getSelector(),
}));
});
}
}
}
Build and create the formatting settings service model in the visual's constructor method.
The formatting settings service receives the barChart format settings and converts them
into a FormattingModel object that's returned in the getFormattingModel API.
To use the localization feature, add the localization manager to the formatting settings
service.
TypeScript
// ...
// declare utils formatting settings service
private formattingSettingsService: FormattingSettingsService;
//...
constructor(options: VisualConstructorOptions) {
this.host = options.host;
const localizationManager = this.host.createLocalizationManager();
this.formattingSettingsService = new
FormattingSettingsService(localizationManager);
Update the formatting settings model using update API. Call the Update API each time a
formatting property in the properties pane is changed. Create bar chart selectors data
points and populate them in formatting settings model:
TypeScript
// ...
// Add the rest of your custom visual update API code here
}
Finally, the new API getFormattingModel is a simple line of code using the formatting
settings service and current formatting settings model that was created in the update
API above.
TypeScript
We already added the enableAxis property to the capabilities file and the
barChartSettings interface.
TypeScript
function getColumnColorByIndex(
category: DataViewCategoryColumn,
index: number,
colorPalette: ISandboxExtendedColorPalette,
): string {
if (colorPalette.isHighContrast) {
return colorPalette.background.value;
}
For more detailed instructions on how to add color to your bar chart go to Add colors to
your Power BI visual.
7 Note
Verify that your final barChart.ts file looks like this barChart.ts source code , or
download the barChart.ts source code and use it to replace your file.
Test the visual
Run the visual in the Power BI server to see how it looks:
1. In PowerShell, navigate to the project's folder and start the development app.
PowerShell
pbiviz start
) Important
Do not close the PowerShell window until the end of the tutorial. To stop the
visual from running, enter Ctrl + C , and if prompted to terminate the batch
job, enter Y , and then Enter .
2. View the visual in Power BI service by selecting the Developer visual from the
Visualization pane.
To prepare the visual for sharing, follow the instructions in Package a Power BI visual.
7 Note
For the full source code of a bar chart with more features, including tool-tips and a
context menu, see Power BI visuals sample bar chart .
Related content
Add a context menu to a visual
Add a landing page to a visual
Add locale support
Feedback
Was this page helpful? Yes No
As a developer you can create your own Power BI visuals. These visuals can be used by
you, your organization or by third parties.
In this tutorial, you develop a Power BI visual using React . The visual displays a
formatted measure value inside a circle. The visual has adaptive size and allows you to
customize its settings.
7 Note
For the full source code of this visual, see React circle card Power BI visual .
Prerequisites
Before you start developing your Power BI visual, verify that you have everything listed
in this section.
A Power BI Pro or Premium Per User (PPU) account. If you don't have one, sign up
for a free trial .
This tutorial uses the US Sales Analysis report. You can download this report and
upload it to Power BI service, or use your own report. If you need more information
about Power BI service, and uploading files, refer to the Get started creating in the
Power BI service tutorial.
1. Open PowerShell and navigate to the folder you want to create your project in.
PowerShell
PowerShell
cd ReactCircleCard
4. Start the React circle card visual. Your visual is now running while being hosted on
your computer.
PowerShell
pbiviz start
) Important
To stop the visual from running, in PowerShell enter Ctrl + C and if prompted
to terminate the batch job, enter Y , and press Enter.
You can also use your own report to test the visual.
7 Note
Before you continue, verify that you enabled the visuals developer settings.
2. Select Edit.
3. Create a new page for testing, by clicking on the New page button at the bottom
of the Power BI service interface.
This visual represents the custom visual that you're running on your computer. It's
only available when the custom visual debugging setting is enabled.
7 Note
If the visual displays a connection error message, open a new tab in your
browser, navigate to https://localhost:8080/assets , and authorize your
browser to use this address.
6. While the new visual is selected, go to the Fields pane, expand Sales, and select
Quantity.
7. To test how the visual is responding, resize it and notice that the Update count
value increments every time you resize the visual.
Open PowerShell and stop the visual from running by entering Ctrl+C. If prompted to
terminate the batch job, enter Y, and press Enter.
Install React
To install the required React dependencies, open PowerShell in your ReactCircleCard
folder, and run the following command:
PowerShell
PowerShell
TypeScript
1. In the src folder, open visual.ts and replace the code in the file with the following
code:
TypeScript
"use strict";
import powerbi from "powerbi-visuals-api";
import "./../style/visual.less";
constructor(options: VisualConstructorOptions) {
}
}
7 Note
2. To render the component, add the target HTML element to visual.ts. This element
is HTMLElement in VisualConstructorOptions , which is passed into the constructor.
Typescript
ReactDOM.render(this.reactRoot, this.target);
Typescript
"use strict";
import powerbi from "powerbi-visuals-api";
import "./../style/visual.less";
constructor(options: VisualConstructorOptions) {
this.reactRoot = React.createElement(ReactCircleCard, {});
this.target = options.element;
ReactDOM.render(this.reactRoot, this.target);
}
}
}
3. Save visual.ts.
Edit the tsconfig file
Edit the tsconfig.json to work with React.
1. In the reactCircleCard folder, open tsconfig.json and add two lines to the
beginning of the compilerOptions item.
JSON
"jsx": "react",
"types": ["react", "react-dom"],
Your tsconfig.json file should now look like this, and the component error in
visual.ts should be gone.
JSON
{
"compilerOptions": {
"jsx": "react",
"types": ["react", "react-dom"],
"allowJs": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "./.tmp/build/",
"moduleResolution": "node",
"declaration": true,
"lib": [
"es2015",
"dom"
]
},
"files": [
"./src/visual.ts"
]
}
2. Save tsconfig.json.
Bash
pbiviz start
When you add a new Developer Visual to your report in the Power BI service, it looks
like this:
2. The ReactCircleCard displays a single value, Measure Data . Remove the Category
Data object from dataRoles .
After removing the Category Data object, the dataRoles key looks like this:
JSON
"dataRoles": [
{
"displayName": "Measure Data",
"name": "measure",
"kind": "Measure"
}
],
3. Remove all the content of the objects key (you'll fill it in later).
After you remove its content, the objects key looks like this:
JSON
"objects": {},
4. Replace the dataViewMappings property with the following code. max: 1 in measure
specifies that only one data field can be submitted to the visual's Measure data
field.
JSON
"dataViewMappings": [
{
"conditions": [
{
"measure": {
"max": 1
}
}
],
"single": {
"role": "measure"
}
}
]
6. Verify that pbiviz start is running and in Power BI service, refresh your React
Circle Card visual. The Measure data field can accept only one data field, as
specified by max: 1 .
css
.circleCard {
position: relative;
box-sizing: border-box;
border: 1px solid #000;
border-radius: 50%;
width: 200px;
height: 200px;
}
p {
text-align: center;
line-height: 30px;
font-size: 20px;
font-weight: bold;
position: relative;
top: -30px;
margin: 50% 0 0 0;
}
3. Save visual.less.
JavaScript
render(){
const { textLabel, textValue } = this.state;
return (
<div className="circleCard">
<p>
{textLabel}
<br/>
<em>{textValue}</em>
</p>
</div>
)
}
}
3. Save component.tsx.
The following code selects textLabel and textValue from DataView , and if the data
exists, updates the component state.
2. Replace the line import ReactCircleCard from "./component"; with the following
code:
TypeScript
TypeScript
ReactCircleCard.update({
textLabel: dataView.metadata.columns[0].displayName,
textValue: dataView.single.value.toString()
});
} else {
this.clear();
}
4. Create a clear method by adding the following code below the update method.
TypeScript
private clear() {
ReactCircleCard.update(initialState);
}
5. Save visual.ts
TypeScript
public componentWillMount() {
ReactCircleCard.updateCallback = (newState: State): void => {
this.setState(newState); };
}
public componentWillUnmount() {
ReactCircleCard.updateCallback = null;
}
3. Save component.tsx.
1. Verify that pbiviz start is running, and in the Power BI service, refresh your React
Circle Card visual.
After you complete the steps outlined in this section, the circle diameter in your visual
will correspond to the minimal width or height size, and you'll be able to resize it in
Power BI service.
TypeScript
TypeScript
this.viewport = options.viewport;
const { width, height } = this.viewport;
const size = Math.min(width, height);
TypeScript
size,
6. Save visual.ts.
TypeScript
size: number
TypeScript
size: 200
TypeScript
TypeScript
TypeScript
5. Save component.tsx.
css
min-width: 200px;
min-height: 200px;
3. Save visual.less.
JSON
"circle": {
"properties": {
"circleColor": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"circleThickness": {
"type": {
"numeric": true
}
}
}
}
3. Save capabilities.json.
TypeScript
"use strict";
/**
* Circle Formatting Card
*/
class CircleCardSettings extends FormattingSettingsCard {
circleColor = new formattingSettings.ColorPicker({
name: "circleColor", // circle color name should match circle
color property name in capabilities.json
displayName: "Color",
description: "The fill color of the circle.",
value: { value: "white" }
});
/**
* visual settings model class
*
*/
export class VisualFormattingSettingsModel extends
FormattingSettingsModel {
// Create formatting settings model circle formatting card
circleCard = new CircleCardSettings();
cards = [this.circleCard];
}
3. Save settings.ts.
TypeScript
TypeScript
TypeScript
5. In the Visual class, add the following code line to constructor to initialize
formattingSettingsService
TypeScript
6. In the Visual class, add the following code to update to update the visual
formatting settings to the latest formatting properties values.
a. Add this code to the if statement after const size = Math.min(width, height); .
TypeScript
this.formattingSettings =
this.formattingSettingsService.populateFormattingSettingsModel(Visua
lFormattingSettingsModel, options.dataViews);
const circleSettings = this.formattingSettings.circleCard;
TypeScript
borderWidth: circleSettings.circleThickness.value,
background: circleSettings.circleColor.value.value,
}
7. Save visual.ts.
TypeScript
background?: string,
borderWidth?: number
TypeScript
TypeScript
4. Save component.tsx.
1. Verify that pbiviz start is running, and in the Power BI service, refresh your React
Circle Card visual.
Next steps
Add formatting options to the circle card visual
Create a Power BI bar chart visual
Learn how to debug a Power BI visual you created
Tutorial: Create an R-powered Power BI
visual
Article • 01/11/2024
As a developer you can create your own Power BI visuals. These visuals can be used by
you, your organization or by third parties.
This article is a step by step guide for creating an R-powered visual for Power BI.
Prerequisites
A Power BI Pro account. Sign up for a free trial before you begin.
An R engine. You can download one free from many locations, including the
Microsoft R Open download page and the CRAN Repository . For more
information, see Create Power BI visuals using R.
Power BI Desktop.
Windows PowerShell version 4 or later for Windows users OR the Terminal for
OSX users.
Get started
1. Prepare some sample data for the visual. You can save these values to an Excel
database or a .csv file and import it into Power BI Desktop.
ノ Expand table
1 2303
2 2319
3 1732
MonthNo Total Units
4 1615
5 1427
6 2253
7 1147
8 1515
9 2516
10 3131
11 3170
12 2762
2. To create a visual, open PowerShell or Terminal, and run the following command:
This command creates a new folder for the rVisualSample visual. The structure is
based on the rvisual template. It creates a file called script.r in the root folder of
the visual. This file holds the R-script that is run to generate the image when the
visual is rendered. You can create your R-script in Power BI Desktop.
3. From the newly created rVisualSample directory run the following command:
pbiviz start
plot(dataset)
This command creates a scatter chart using the values in the semantic model as
input.
4. In the capabilities.json file, change the dataRoles : name to dataset, and set the
dataViewMappings input to dataset.
JSON
{
"dataRoles": [
{
"displayName": "Values",
"kind": "GroupingOrMeasure",
"name": "dataset"
}
],
"dataViewMappings": [
{
"scriptResult": {
"dataInput": {
"table": {
"rows": {
"select": [
{
"for": {
"in": "dataset"
}
}
],
"dataReductionAlgorithm": {
"top": {}
}
}
}
},
...
}
}
],
}
5. Add the following code to support resizing the image in the src/visual.ts file.
TypeScript
JSON
{
"cranPackages": [
{
"name": "corrplot",
"displayName": "corrplot",
"url": "https://cran.r-project.org/web/packages/corrplot/"
}
]
}
2. Now you can start using the corrplot package in your script.r file.
R
library(corrplot)
corr <- cor(dataset)
corrplot(corr, method="circle", order = "hclust")
We use the method argument to configure the shape of the data points. The default
script uses a circle. Modify your visual to let the user choose between several options.
1. Define an object called settings in the capabilities.json file and give it the following
properties. Then use this object name in the enumeration method to get the values
from the property pane.
JSON
{
"settings": {
"displayName": "Visual Settings",
"description": "Settings to control the look and feel of the visual",
"properties": {
"method": {
"displayName": "Data Look",
"description": "Control the look and feel of the data points in
the visual",
"type": {
"enumeration": [
{
"displayName": "Circle",
"value": "circle"
},
{
"displayName": "Square",
"value": "square"
},
{
"displayName": "Ellipse",
"value": "ellipse"
},
{
"displayName": "Number",
"value": "number"
},
{
"displayName": "Shade",
"value": "shade"
},
{
"displayName": "Color",
"value": "color"
},
{
"displayName": "Pie",
"value": "pie"
}
]
}
}
}
}
2. Open the src/settings.ts file. Create a CorrPlotSettings class with the public
property method . The type is string and the default value is circle . Add the
settings property to the VisualSettings class with the default value:
TypeScript
"use strict";
/**
/**
*/
export class VisualFormattingSettingsModel extends
FormattingSettingsModel {
// Create formatting settings model formatting cards
rcvScriptCard = new rcvScriptCardSettings();
cards = [this.rcvScriptCard];
}
After these steps, you can change the property of the visual.
Finally, the R-script must have a default property. If the user doesn't change the
property value (in this case, the shape setting), the visual uses this value.
library(corrplot)
corr <- cor(dataset)
if (!exists("settings_method"))
{
settings_method = "circle";
}
1. Fill in the displayName , supportUrl , description , author's name and email , and
any other important information in the pbiviz.json file.
2. If you want to change the visual's icon on the visualization pane, replace the
icon.png file in the assets folder.
PowerShell
pbiviz package
For more information on packaging your visual see Packaging the custom visual
4. Import the visual's pbiviz file to any Power BI report. See Import a visual file from
your local computer into Power BI for instructions on how to do this.
Related content
Use R-powered Power BI visuals in Power BI.
This article describes how to build a funnel plot using R script in R visual step by step.
Source files are available for download under each set of steps.
The funnel plot provides an easy way to consume, interpret, and show the amount of
expected variation. The funnel is formed using confidence limits and outliers are shown
as dots outside the funnel.
In this example the funnel plot is used to compare and analyze various sets data.
Prerequisites
Get a Microsoft Fabric subscription. Or, sign up for a free Microsoft Fabric trial.
2. Next, edit the script to mirror this script . This adds input error handling and user
parameters to control the plot's appearance.
Build a report
Next, edit the script to mirror this script . This loads dataset.csv instead of read.csv into
the Power BI desktop workspace and creates a Cancer Mortality table. See the results in
the following PBIX file .
7 Note
The dataset is a hard-coded name for the input data.frame of any R-visual.
Bash
This command creates the folder funnel-visual with initial template visual ( -t for
template). The PBIVIZ can be found in the dist folder, the R-code inside script.r file.
Try to import it into Power BI and see what happens.
2. Edit script.r file and replace the contents with your previous script.
3. Edit capabilities.json and replace the string Values with dataset . This replaces the
name of "Role" in the template to be like in R-code.
4. (optional) Edit dependencies.json and add a section for each R package required by
the R script. This tells Power BI to automatically import these packages when the
visual is loaded for the first time.
5. Repackage the visual using the pbiviz package command and try to import it into
Power BI.
7 Note
1. Divide the input field dataset into three fields (roles): Population , Number , and
Tooltips
2. Edit capabilities.json and replace the dataset role with the three new roles, or
download capabilities.json .
4. Repackage the visual using the pbiviz package command and try to import it into
Power BI.
7 Note
4. Edit script.r to mirror this script.r . This adds support for the parameters in the UI
by adding if.exists calls per user-parameter.
Tip
You can decide not to expose the parameters to the UI, like we did.
5. Repackage the visual using the pbiviz package command and try to import it into
Power BI.
7 Note
Tip
Here we added parameters of several types (boolean, numeric, string, and color) all
at once. For a simple case, please see this example on how to add a single
parameter.
Bash
4. Open script.r and note the structure. You can open and run it in RStudio since it
doesn't use external input.
This creates and saves out.html. This file is self-contained (with no external
dependencies) and defines the graphics inside the HTML widget.
) Important
For htmlWidgets users, R-utilities are provided in the r_files folder to help
convert plotly or widget objects into self-content HTML.
This version of R-powered visual also supports the source command (unlike
previous types of visuals), to make your code more readable.
Be sure to keep:
"scriptOutputType": "html"
6. Merge the latest version of script.r with the script.r from the template, or download
script.r .
The new script uses the plotly package to convert the ggplot object into a plotly
object, then the htmlWidgets package to save it to an HTML file.
Most of the utility functions are moved to r_files/utils.r and the
generateNiceTooltips function is added for the appearance of the plotly object.
Tip
7. Merge the latest version of dependencies.json with the dependencies.json from the
template, to include new R-package dependencies, or download
dependencies.json .
7 Note
Bash
2. Take code from this showcase and make the highlighted changes:
3. Replace your template's script.r and run pbiviz package again. Now the visual is
included in your Power BI report!
) Important
The guid field is the unique identifier for a visual. If you create a new project
for each visual, the GUID will be also be different. It's only the same when
using an old project copied to a new visual, which you shouldn't do.
To debug R-code in RStudio using the same data as in your Power BI report, add
the following to the beginning of the R-script (edit the fileRda variable):
#DEBUG in RStudio
fileRda = "C:/Users/yourUserName/Temp/tempData.Rda"
if(file.exists(dirname(fileRda)))
{
if(Sys.getenv("RSTUDIO")!="")
load(file= fileRda)
else
save(list = ls(all.names = TRUE), file=fileRda)
}
This saves the environment from a Power BI report and loads it into RStudio.
You don't need to develop R-powered Visuals from scratch with code available on
GitHub . You can select the visual to use as a template and copy the code into a
new project.
Each R Visual applies the unique operator to its input table. To avoid identical rows
being removed, consider adding an extra input field with a unique ID and ignore it
in the R code.
If you have a Power BI account, use the Power BI service to develop a visual on-
the-fly instead of repackaging them with the pbiviz package command.
Tip
To switch between html widgets use Format > Settings > Type. Try it out with this
PBIX file .
To use a sample for your visual
1. Download the entire folder.
2. Edit script.r and dependencies.json to keep only one widget.
3. Edit capabilities.json and settings.ts to remove the Type selector.
4. Change const updateHTMLHead: boolean = true; to false in visual.ts. (for better
performance)
5. Change metadata in pbiviz.json, most importantly the guid field.
6. Repackage and continue to customize the visual as wanted.
7 Note
Not all widgets in this project are supported by the service.
Related content
To learn more, see additional Power BI tutorials, Developing a Power BI circle card visual
and R visuals.
Learn how to develop and submit visuals to the Office Store (gallery) , or for further
examples, see the R-script showcase
Feedback
Was this page helpful? Yes No
Power BI comes with many out-of-the-box visuals that are available in the Visualizations
pane of both Power BI Desktop and Power BI Service .
Many more certified Power BI visuals are available from AppSource . These visuals are
created by Microsoft and Microsoft partners, and are validated by the AppSource
validation team. You can download these visuals directly to your Visualizations pane.
You can also develop your own Power BI visual, or get one from a trusted friend or
coworker.
If you download or receive a Power BI visual file, you have to import it to the
Visualizations pane before you can use it to create Power BI content.
7. The visual now appears as a new icon in the visualizations pane of the current
report. Select the visual's icon to create the visual on the report canvas.
8. If you want the visual to remain on the Visualizations pane so you can use it in
future reports, right-click the visual's icon and select Pin to visualization pane.
4. If you get a message cautioning you about importing custom files, select Import if
you trust the source of the file.
5. Navigate to the folder that has the custom visual file (.pbiviz) and open it.
7. The visual now appears as a new icon in the visualizations pane of the current
report. Select the new visual icon to create the visual on the report canvas.
8. If you want the visual to remain on the Visualizations pane so you can use it in
future reports, right-click the visual's icon and select Pin to visualization pane.
Related content
Developing a Power BI circle card visual
Visualizations in Power BI
Organizational visuals
How can the admin manage access to
organizational Power BI custom visuals?
In the Admin portal, under the Organizational visuals tab, the admin can see and
manage all the organizational Power BI visuals in the enterprise. This includes adding,
disabling, enabling, and deleting Power BI visuals.
Users in the organization can easily find Power BI visuals, and import them into their
reports directly from Power BI Desktop or Service.
Once the admin uploads a new version of an organizational Power BI visual, everyone in
the organization gets the same updated version. All reports using updated Power BI
visuals are automatically updated.
Users can find the organizational Power BI visuals in the built-in Power BI Desktop and
Power BI Service organization store, under the MY ORGANIZATION tab.
Some organizations disable Power BI visuals and enable only hand-picked visuals that
were imported and uploaded by the Power BI admin to the organizational store.
Disabling the Power BI visuals from the Admin portal isn't enforced in Power BI Desktop.
Desktop users can still add and use Power BI visuals from the public marketplace in their
reports. However, those public Power BI visuals stop rendering once published to the
Power BI Service and issue an appropriate error.
When the Power BI visuals setting in the Admin portal, is enforced, users in Power BI
Service can't import Power BI visuals from the public marketplace. Only visuals from the
organizational store can be imported.
No need to share visual files by email or shared folders. The organizational store
offers are visible to all members who are logged in.
Admins can control which Power BI visuals are available throughout the
organization.
Admins can enable/disable visuals for testing from the Admin portal.
Certified Power BI visuals
What are certified Power BI visuals?
Certified Power BI visuals are Power BI visuals that meet certain requirements, and are
certified by Microsoft.
In the marketplace , certified Power BI visuals have a yellow badge indicating that
they're certified.
Code reviews
Static code analysis
Data leakage
Data fuzzing
Penetration testing
Access XSS testing
Malicious data injection
Input validation
Functional testing
Provide read permissions to check the Power BI visual code. For example, by using a
private repository in GitHub.
Some visuals aren't certified because they don't comply with one or more of the
certification requirements. For example, connecting to an external service like map
visuals, or visuals using commercial libraries.
Visuals with additional purchases
What is a visual with additional purchases?
A visual with additional purchases is similar to in-app purchase (IAP) adds-in. These
adds-in include an Additional purchase may be required price tag.
IAP Power BI visuals are free, downloadable Power BI visuals. Users pay nothing to
download those Power BI visuals from the marketplace.
When registering your Power BI visual, navigate to the Product setup tab and check the
My product requires the purchase of a service check box.
7 Note
Power BI free visuals with an added IAP feature must keep the same free features
previously offered. You can add optional advanced paid features on top of the old
free features. We recommend submitting the IAP Power BI visual with the advanced
features as a new Power BI visual, and not to update the old free one.
Certification is an optional process. It's up to you to decide if you want your IAP visual to
be certified.
More questions
How to get support?
Contact the Power BI visuals support team [email protected] with any
questions, comments, or issues you have. This support channel is for custom visuals
developers in the process of developing their own visuals.
For customer experience issues when using custom Power BI visuals, submit a case
request via the Power Platform admin center portal .
Related content
For more information, see Troubleshooting your Power BI visuals.
Feedback
Was this page helpful? Yes No
This article describes some of the Power BI visuals you can download, use, and modify
from GitHub. These sample visuals illustrate how to handle common situations when
developing with Power BI.
Slicers
A slicer narrows the portion of data shown in other visualizations in a report. Slicers are
one of several ways to filter data in Power BI.
ノ Expand table
Slicer sample
Demonstrates the use of the Advanced Filtering API
Charts
Get inspired with our gallery of Power BI visuals, including bar charts, pie charts, Word
Cloud, and others.
ノ Expand table
WebGL
WebGL lets web content use an API based on OpenGL ES 2.0 to do 2D and 3D rendering
in an HTML canvas.
ノ Expand table
Globe Map
Plot locations on an interactive 3D map
R visuals
These examples demonstrate how to harness the analytic and visual power of R visuals
and R scripts.
ノ Expand table
Related content
Import a Power BI visual
Develop your own Power BI custom visual
Feedback
Was this page helpful? Yes No
This article teaches you how to set up your environment for developing a Power BI
visual.
Before you start development, you need to install node.js and the pbiviz package. Then,
when your local environment is set up, you need to configure Power BI service for
developing a Power BI visual.
" Install node.js.
" Install pbiviz.
" Set up the Power BI desktop for developing a visual
" Set up Power BI service for developing a visual.
Install node.js
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It allows
developers to run any apps created on JavaScript.
To install node.js:
3. Run the installer, and then follow the installation steps. Accept the terms of the
license agreement and all defaults.
Install pbiviz
The pbiviz tool, which is written using JavaScript, compiles the visual source code of the
pbiviz package.
The pbiviz package is a zipped Power BI visual project, with all the needed scripts and
assets.
To install the latest version of pbiviz, open Windows PowerShell and enter the following
command.
PowerShell
npm i -g powerbi-visuals-tools@latest
7 Note
You might get some warnings when you run this command. They should not
prevent pbiviz from installing.
1. From the Power BI desktop, navigate to File > Options and settings > Options
2. Scroll down to Report settings in the Current file section, and enable the Develop a
visual check box.
3. Select OK
2. Enable the Power BI Developer mode switch. check box, and then select Apply.
Related content
Learn about the Power BI visual project structure
Create a Power BI circle card visual
Create an R-powered Power BI visual
Feedback
Was this page helpful? Yes No
The best way to start creating a new Power BI visual is to use the Power BI visuals
pbiviz tool.
To create a new visual, navigate to the directory you want the Power BI visual to reside
in, and run the command:
Running this command creates a Power BI visual folder that contains the following files:
markdown
project
├───.vscode
│ ├───launch.json
│ └───settings.json
├───assets
│ └───icon.png
├───node_modules
├───src
│ ├───settings.ts
│ └───visual.ts
├───style
│ └───visual.less
├───capabilities.json
├───package-lock.json
├───package.json
├───pbiviz.json
├───tsconfig.json
└───tslint.json
.vscode
This folder contains the VS Code project settings.
assets
This folder contains the icon.png file.
The Power BI visuals tool uses this file as the new Power BI visual icon in the Power BI
visualization pane. This icon must be a PNG file with dimensions 20 pixels by 20 pixels.
src
This folder contains the visual's source code.
In this folder, the Power BI visuals tool creates the following files:
visual.ts - The visual's main source code. Read about the Visual API.
settings.ts - The code of the visual's settings. The classes in the file provide an
style
This folder contains the visual.less file, which holds the visual's styles.
capabilities.json
This file contains the main properties and settings (or capabilities) for the visual. It allows
the visual to declare supported features, objects, properties, and data view mapping.
package-lock.json
This file is automatically generated for any operations where npm modifies either the
node_modules tree, or the package.json file.
For more information about this file, see the official npm-package-lock.json
documentation.
package.json
This file describes the project package. It contains information about the project such as
authors, description, and project dependencies.
For more information about this file, see the official npm-package.json
documentation.
pbiviz.json
This file contains the visual metadata.
To view an example pbiviz.json file with comments describing the metadata entries,
see the metadata entries section.
tsconfig.json
A configuration file for TypeScript .
This file must contain the path to *.ts file where the main class of the visual is located, as
specified in the visualClassName property in the pbiviz.json file.
tslint.json
This file contains the TSLint configuration .
Metadata entries
The comments in the following code caption from the pbiviz.json file describe the
metadata entries. Certain metadata, like the author's name and email, are required
before you can package the visual.
7 Note
JSON
{
"visual": {
// The visual's internal name.
"name": "<visual project name>",
// The name of the visual's main class. Power BI creates the instance of
this class to start using the visual in a Power BI report.
"visualClassName": "Visual",
// 'icon' holds the path to the icon file in the assets folder; the
visual's display icon.
"assets": { "icon": "assets/icon.png" },
Related content
Power BI visuals system integration
Develop a Power BI circle card visual
Feedback
Was this page helpful? Yes No
The article describes the Visual API, and how Power BI handles the interactions between
you, the visual, and the host.
The following figure shows how common visual-based actions, like selecting a
bookmark, process in Power BI.
Interact with a visual through Power BI
You can update a visual with Power BI as follows:
When you open the visual's properties panel, Power BI fetches supported objects
and properties from the visual's capabilities.json file. To receive actual values of
properties, Power BI calls the getFormattingModel method of the visual (APIs earlier
than version 5.0 call enumerateObjectInstances instead). The API returns modern
format pane model components, properties, and their actual values.
For more information, see Capabilities and properties of Power BI visuals.
When you change the value of a property in the Format panel, Power BI calls the
update method. Power BI passes in the new options object to the update method,
When you change the size of a visual, Power BI calls the update method and
passes in the new options object. The options objects have nested viewport
objects that contain the new width and height of the visual.
Power BI filters data based on filter conditions. Power BI calls the update method
of the visual to update the visual with new data.
The visual gets a new update of the options objects when there's new data in one
of the nested objects. How the update occurs depends on the data view mapping
configuration of the visual.
For more information, see Understand data view mapping in Power BI visuals.
When you select a data point in another visual in the report, Power BI filters or
highlights the selected data points and calls the visual's update method. The visual
gets new filtered data, or it gets the same data with an array of highlights.
Power BI calls the update method with a corresponding filter object inside
the options object.
In both cases, the visual changes its state according to the received selections or
filter object.
For more information about bookmarks and filters, see Visual Filters API in
Power BI visuals.
A visual can display more information about a data point through the Power BI
Tooltips API. When you hover over a visual element, the visual can handle the
event and display data about the associated tooltip element. The visual can display
either a standard tooltip or a report page tooltip.
Change visual properties (For example, by expanding a tree) and the visual saves
the new state in the visual properties.
A visual can save properties values through the Power BI API. For example, when
you interact with the visual and the visual needs to save or update properties
values, the visual can call the persistProperties method.
Select a URL.
By default, a visual can't open a URL directly. To open a URL in a new tab, the visual
can call the launchUrl method and pass the URL as a parameter.
A visual can call the applyJsonFilter method and pass conditions to filter for data
in other visuals. Several types of filters are available, including Basic, Advanced, and
Tuple filters.
For more information about selections in a Power BI visual, see Add interactivity
into visual by Power BI visual selections.
Visual interacts with Power BI
Sometimes the visual initiates communication with the Power BI host without any input
from you:
A visual processes data part by part. The fetchMoreData API method requests the
next fragment of data in the semantic model.
For more information, see Fetch more data from Power BI.
Power BI can export a report to PDF or send a report by e-mail (applies only to
certified visuals). To notify Power BI that rendering is finished and that the visual is
ready to be captured as PDF or e-mail, the visual should call the Rendering Events
API.
To learn about the event service, see "Rendering" events in Power BI visuals.
Related content
Interested in creating visualizations and adding them to Microsoft AppSource? See
these articles:
Visual API
Develop a Power BI circle card visual
Publish Power BI visuals to Microsoft commercial marketplace
Feedback
Was this page helpful? Yes No
Every visual has a capabilities.json file that is created automatically when you run the
pbiviz new <visual project name> command to create a new visual. The capabilities.json
The capabilities.json file tells the host what kind of data the visual accepts, what
customizable attributes to put on the properties pane, and other information needed to
create the visual. Starting from API v4.6.0, all properties on the capabilities model are
optional except privileges , which are required.
The capabilities.json file lists the root objects in the following format:
JSON
{
"privileges": [ ... ],
"dataRoles": [ ... ],
"dataViewMappings": [ ... ],
"objects": { ... },
"supportsHighlight": true|false,
"advancedEditModeSupport": 0|1|2,
"sorting": { ... }
...
}
When you create a new visual, the default capabilities.json file includes the following
root objects:
privileges
dataRoles
dataViewMappings
objects
The above objects are the ones needed for data-binding. They can be edited as
necessary for your visual.
The following additional root objects are optional and can be added as needed:
tooltips
supportsHighlight
sorting
drilldown
expandCollapse
supportsKeyboardFocus
supportsSynchronizingFilterState
advancedEditModeSupport
supportsLandingPage
supportsEmptyDataView
supportsMultiVisualSelection
subtotals
keepAllMetadataColumns
migration
You can find all these objects and their parameters in the capabilities.json schema
7 Note
From API v4.6.0, privileges must be specified in the capabilities.json file. In earlier
versions, remote access is automatically granted and downloading to files isn't
possible. To find out which version you’re using, check the apiVersion in the
pbiviz.json file.
Define privileges
A JSON privilege definition contains these components:
privilege. A value of true means the privilege is required; false means the
privilege isn't mandatory.
parameters - (string array)(optional) Arguments. If parameters is missing, it's
7 Note
Even with these privileges granted in the visual, the admin has to enable the switch
in the admin settings to allow people in their organization to benefit from these
settings.
To allow a visual to access an external resource or web site, add that information as a
privilege in the capabilities section. The privilege definition includes an optional list of
URLs the visual is allowed to access in the format http://xyz.com or https://xyz.com .
Each URL can also include a wildcard to specify subdomains.
JSON
{
"name": "WebAccess",
"essential": true,
"parameters": [ "https://*.microsoft.com", "http://example.com" ]
}
The preceding WebAccess privilege means that the visual needs to access any
subdomain of the microsoft.com domain via HTTPS protocol only and example.com
without subdomains via HTTP, and that this access privilege is essential for the visual to
work.
Download to file
To allow the user to export data from a visual into a file, set ExportContent to true .
This ExportContent setting enables the visual to export data to files in the following
formats:
.txt
.csv
.json
.tmplt
.xml
.pdf
.xlsx
This setting is separate from and not affected by download restrictions applied in the
organization's export and sharing tenant settings.
JSON
"privileges": [
{
"name": "ExportContent",
"essential": true
}
]
This privilege allows a custom visual to store information on the user's local browser.
The following is an example of a privileges setting that allows use of the local storage:
JSON
"privileges": [
{
"name": "LocalStorage",
"essential": true
}
]
No privileges needed
If the visual doesn't requires any special permissions, the privileges array should be
empty:
JSON
"privileges": []
Multiple privileges
The following example shows how to set several privileges for a custom visual.
JSON
"privileges": [
{
"name": "WebAccess",
"essential": true,
"parameters": [ "https://*.virtualearth.net" ]
},
{
"name": "ExportContent",
"essential": false
}
]
The user drags data fields into them to bind data the data fields to the objects.
DataRole properties
DataRoles are defined by the following properties:
dataRoles example
JSON
"dataRoles": [
{
"displayName": "My Category Data",
"name": "myCategory",
"kind": "Grouping",
"requiredTypes": [
{
"text": true
},
{
"numeric": true
},
{
"integer": true
}
],
"preferredTypes": [
{
"text": true
}
]
},
{
"displayName": "My Measure Data",
"name": "myMeasure",
"kind": "Measure",
"requiredTypes": [
{
"integer": true
},
{
"numeric": true
}
],
"preferredTypes": [
{
"integer": true
}
]
}
]
...
}
The preceding data roles would create the fields that are displayed in the following
image:
Most visuals provide a single mapping, but you can provide multiple
dataViewMappings. Each valid mapping produces a data view.
JSON
"dataViewMappings": [
{
"conditions": [ ... ],
"categorical": { ... },
"table": { ... },
"single": { ... },
"matrix": { ... }
}
]
For more information, see Understand data view mapping in Power BI visuals.
JSON
"objects": {
"myCustomObject": {
"properties": { ... }
}
}
For example, to support dynamic format strings in your custom visual, define the
following object:
JSON
"objects": {
"general": {
"properties": {
"formatString": {
"type": {
"formatting": {
"formatString": true
}
}
}
}
},
Related content
Understand data view mapping in Power BI visuals
Objects and properties of Power BI visuals
Sorting options for Power BI visuals
Understand data view mapping in
Power BI visuals
Article • 12/12/2023
This article discusses data view mapping and describes how data roles are used to
create different types of visuals. It explains how to specify conditional requirements for
data roles and the different dataMappings types.
Each valid mapping produces a data view. You can provide multiple data mappings
under certain conditions. The supported mapping options are:
conditions
categorical
single
table
matrix
JSON
"dataViewMappings": [
{
"conditions": [ ... ],
"categorical": { ... },
"single": { ... },
"table": { ... },
"matrix": { ... }
}
]
Power BI creates a mapping to a data view only if the valid mapping is also defined in
dataViewMappings .
JSON
"dataViewMappings": [
{
"categorical": {
"categories": [ ... ],
"values": [ ... ]
},
"metadata": { ... }
}
]
Conditions
The conditions section establishes rules for a particular data mapping. If the data
matches one of the described sets of conditions, the visual accepts the data as valid.
For each field, you can specify a minimum and maximum value. The value represents the
number of fields that can be bound to that data role.
7 Note
If a data role is omitted in the condition, it can have any number of fields.
In the following example, the category is limited to one data field and the measure is
limited to two data fields.
JSON
"conditions": [
{ "category": { "max": 1 }, "measure": { "max": 2 } },
]
You can also set multiple conditions for a data role. In that case, the data is valid if any
one of the conditions is met.
JSON
"conditions": [
{ "category": { "min": 1, "max": 1 }, "measure": { "min": 2, "max": 2 }
},
{ "category": { "min": 2, "max": 2 }, "measure": { "min": 1, "max": 1 }
}
]
To use single data mapping, define the name of the data role that you want to map. This
mapping works only with a single measure field. If a second field is assigned, no data
view is generated, so it's good practice to include a condition that limits the data to a
single field.
7 Note
This data mapping can't be used in conjunction with any other data mapping. It's
meant to reduce data to a single numeric value.
For example:
JSON
{
"dataRoles": [
{
"displayName": "Y",
"name": "Y",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"Y": {
"max": 1
}
}
],
"single": {
"role": "Y"
}
}
]
}
The resulting data view can still contain other types of mapping, like table or categorical,
but each mapping contains only the single value. The best practice is to access the value
only in single mapping.
JSON
{
"dataView": [
{
"metadata": null,
"categorical": null,
"matrix": null,
"table": null,
"tree": null,
"single": {
"value": 94163140.3560001
}
}
]
}
TypeScript
"use strict";
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import DataViewSingle = powerbi.DataViewSingle;
// standard imports
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.valueText = document.createElement("p");
this.target.appendChild(this.valueText);
// ...
}
if (!singleDataView ||
!singleDataView.value ) {
return
}
this.valueText.innerText = singleDataView.value.toString();
}
}
The previous code sample results in the display of a single value from Power BI:
JSON
"dataRoles":[
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Y Axis",
"name": "measure",
"kind": "Measure"
}
],
"dataViewMappings": {
"categorical": {
"categories": {
"for": { "in": "category" }
},
"values": {
"select": [
{ "bind": { "to": "measure" } }
]
}
}
}
The previous example reads "Map my category data role so that for every field I drag
into category , its data is mapped to categorical.categories . Also, map my measure
data role to categorical.values ."
for...in: Includes all items in this data role in the data query.
bind...to: Produces the same result as for...in but expects the data role to have a
condition restricting it to a single field.
JSON
"dataRole":[
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Y Axis",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Grouping with",
"name": "grouping",
"kind": "Grouping"
},
{
"displayName": "X Axis",
"name": "measure2",
"kind": "Grouping"
}
],
"dataViewMappings":{
"categorical": {
"categories": {
"for": { "in": "category" }
},
"values": {
"group": {
"by": "grouping",
"select":[
{ "bind": { "to": "measure" } },
{ "bind": { "to": "measure2" } }
]
}
}
}
}
The difference between this mapping and the basic mapping is how categorical.values
is mapped. When you map the measure and measure2 data roles to the data role
grouping , the x-axis and y-axis can be scaled appropriately.
JSON
"dataRoles": [
{
"displayName": "Categories",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measures",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Series",
"name": "series",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"group": {
"by": "series",
"select": [{
"for": {
"in": "measure"
}
}
]
}
}
}
}
]
ノ Expand table
Mexico 645 x x x
UK x x 831 x
Power BI produces a categorical data view with the following set of categories.
JSON
{
"categorical": {
"categories": [
{
"source": {...},
"values": [
"Canada",
"USA",
"UK",
"Mexico"
],
"identity": [...],
"identityFields": [...],
}
]
}
}
Each category maps to a set of values . Each of these values is grouped by series ,
which is expressed as years.
For example, each values array represents one year. Also, each values array has four
values: Canada, USA, UK, and Mexico.
JSON
{
"values": [
// Values for year 2013
{
"source": {...},
"values": [
null, // Value for `Canada` category
null, // Value for `USA` category
null, // Value for `UK` category
645 // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2014
{
"source": {...},
"values": [
630, // Value for `Canada` category
null, // Value for `USA` category
null, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2015
{
"source": {...},
"values": [
490, // Value for `Canada` category
650, // Value for `USA` category
831, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2016
{
"source": {...},
"values": [
null, // Value for `Canada` category
350, // Value for `USA` category
null, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
}
]
}
The following code sample is for processing categorical data view mapping. This sample
creates the hierarchical structure Country/Region > Year > Value.
TypeScript
"use strict";
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import DataViewCategorical = powerbi.DataViewCategorical;
import DataViewValueColumnGroup = powerbi.DataViewValueColumnGroup;
import PrimitiveValue = powerbi.PrimitiveValue;
// standard imports
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.categories = document.createElement("pre");
this.target.appendChild(this.categories);
// ...
}
if (!categoricalDataView ||
!categoricalDataView.categories ||
!categoricalDataView.categories[0] ||
!categoricalDataView.values) {
return;
}
For example, use the same data in the previous section, but with the following
capabilities:
JSON
"dataRoles": [
{
"displayName": "Column",
"name": "column",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"select": [
{
"for": {
"in": "column"
}
},
{
"for": {
"in": "value"
}
}
]
}
}
}
]
ノ Expand table
USA 2015 50
Canada 2015 50
UK 2014 150
USA 2015 75
Data binding:
Power BI displays your data as the table data view. Don't assume that the data is ordered.
JSON
{
"table" : {
"columns": [...],
"rows": [
[
"Canada",
2014,
630
],
[
"Canada",
2015,
490
],
[
"Mexico",
2013,
645
],
[
"UK",
2014,
831
],
[
"USA",
2015,
650
],
[
"USA",
2016,
350
]
]
}
}
To aggregate the data, select the desired field and then choose Sum.
TypeScript
"use strict";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
// ...
import DataViewMetadataColumn = powerbi.DataViewMetadataColumn;
import DataViewTable = powerbi.DataViewTable;
import DataViewTableRow = powerbi.DataViewTableRow;
import PrimitiveValue = powerbi.PrimitiveValue;
// standard imports
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.table = document.createElement("table");
this.target.appendChild(this.table);
// ...
}
if (!tableDataView) {
return
}
while(this.table.firstChild) {
this.table.removeChild(this.table.firstChild);
}
//draw header
const tableHeader = document.createElement("th");
tableDataView.columns.forEach((column: DataViewMetadataColumn) => {
const tableHeaderColumn = document.createElement("td");
tableHeaderColumn.innerText = column.displayName
tableHeader.appendChild(tableHeaderColumn);
});
this.table.appendChild(tableHeader);
//draw rows
tableDataView.rows.forEach((row: DataViewTableRow) => {
const tableRow = document.createElement("tr");
row.forEach((columnValue: PrimitiveValue) => {
const cell = document.createElement("td");
cell.innerText = columnValue.toString();
tableRow.appendChild(cell);
})
this.table.appendChild(tableRow);
});
}
}
The visual styles file style/visual.less contains the layout for the table:
less
table {
display: flex;
flex-direction: column;
}
tr, th {
display: flex;
flex: 1;
}
td {
flex: 1;
border: 1px solid black;
}
JSON
{
"dataRoles": [
{
"name": "Category",
"displayName": "Category",
"displayNameKey": "Visual_Category",
"kind": "Grouping"
},
{
"name": "Column",
"displayName": "Column",
"displayNameKey": "Visual_Column",
"kind": "Grouping"
},
{
"name": "Measure",
"displayName": "Measure",
"displayNameKey": "Visual_Values",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"matrix": {
"rows": {
"for": {
"in": "Category"
}
},
"columns": {
"for": {
"in": "Column"
}
},
"values": {
"select": [
{
"for": {
"in": "Measure"
}
}
]
}
}
}
]
}
Semantic model:
ノ Expand table
JSON
{
"metadata": {...},
"matrix": {
"rows": {
"levels": [...],
"root": {
"childIdentityFields": [...],
"children": [
{
"level": 0,
"levelValues": [...],
"value": "Parent1",
"identity": {...},
"childIdentityFields": [...],
"children": [
{
"level": 1,
"levelValues": [...],
"value": "Child1",
"identity": {...},
"childIdentityFields": [...],
"children": [
{
"level": 2,
"levelValues": [...],
"value": "Grand child1",
"identity": {...},
"values": {
"0": {
"value": 5 // value for Col1
},
"1": {
"value": 6 // value for Col2
}
}
},
...
]
},
...
]
},
...
]
}
},
"columns": {
"levels": [...],
"root": {
"childIdentityFields": [...],
"children": [
{
"level": 0,
"levelValues": [...],
"value": "Col1",
"identity": {...}
},
{
"level": 0,
"levelValues": [...],
"value": "Col2",
"identity": {...}
},
...
]
}
},
"valueSources": [...]
}
}
Expand and collapse commands can be added to the context menu by supplying the
dataRoles parameter to the showContextMenu method.
To expand a large number of data points, use the fetch more data API with the
expand/collapse API.
API features
The following elements have been added to API version 4.1.0 to enable expanding and
collapsing row headers:
TypeScript
interface DataViewTreeNode {
//...
/**
* TRUE if the node is Collapsed
* FALSE if it is Expanded
* Undefined if it cannot be Expanded (e.g. subtotal)
*/
isCollapsed?: boolean;
}
interface ISelectionManager {
//...
showContextMenu(selectionId: ISelectionId, position: IPoint,
dataRoles?: string): IPromise<{}>; // dataRoles is the name of the role
of the selected data point
toggleExpandCollapse(selectionId: ISelectionId, entireLevel?:
boolean): IPromise<{}>; // Expand/Collapse an entire level will be
available from API 4.2.0
//...
}
TypeScript
interface DataViewHierarchyLevel {
//...
/** If TRUE, this level can be expanded/collapsed */
canBeExpanded?: boolean;
}
Visual requirements
To enable the expand collapse feature on a visual by using the matrix data view:
JSON
"expandCollapse": {
"roles": ["Rows"], //”Rows” is the name of rows data role
"addDataViewFlags": {
"defaultValue": true //indicates if the DataViewTreeNode will
get the isCollapsed flag by default
}
},
JSON
"drilldown": {
"roles": ["Rows"]
},
3. For each node, create an instance of the selection builder by calling the
withMatrixNode method in the selected node hierarchy level and creating a
TypeScript
TypeScript
7 Note
If the selected node is not a row node, PowerBI will ignore expand and
collapse calls and the expand and collapse commands will be removed from
the context menu.
The dataRoles parameter is required for the showContextMenu method only if
the visual supports drilldown or expandCollapse features. If the visual
supports these features but the dataRoles wasn't supplied, an error will output
to the console when using the developer visual or if debugging a public visual
with debug mode enabled.
JSON
"keepAllMetadataColumns": {
"type": "boolean",
"description": "Indicates that visual is going to receive all metadata
columns, no matter what the active projections are"
}
Setting this property to true will result in receiving all the metadata, including from
collapsed columns. Setting it to false or leaving it undefined will result in receiving
metadata only on columns with active projections (expanded, for example).
The count is set to the maximum number of values that the data view can accept. If
there are more than count values, the data reduction algorithm determines which values
should be received.
top : The first count values are taken from the semantic model.
bottom : The last count values are taken from the semantic model.
sample : The first and last items are included, and count number of items with equal
intervals between them. For example, if you have a semantic model [0, 1, 2, ... 100]
and a count of 9, you receive the values [0, 10, 20 ... 100].
window : Loads one window of data points at a time containing count elements.
Currently, top and window are equivalent. In the future, a windowing setting will be
fully supported.
By default, all Power BI visuals have the top data reduction algorithm applied with the
count set to 1000 data points. This default is equivalent to setting the following
properties in the capabilities.json file:
JSON
"dataReductionAlgorithm": {
"top": {
"count": 1000
}
}
You can modify the count value to any integer value up to 30000. R-based Power BI
visuals can support up to 150000 rows.
In categorical data mapping, you can add the algorithm to the "categories" and/or
"group" section of values for categorical data mapping.
JSON
"dataViewMappings": {
"categorical": {
"categories": {
"for": { "in": "category" },
"dataReductionAlgorithm": {
"window": {
"count": 300
}
}
},
"values": {
"group": {
"by": "series",
"select": [{
"for": {
"in": "measure"
}
}
],
"dataReductionAlgorithm": {
"top": {
"count": 100
}
}
}
}
}
}
In table data view mapping, apply the data reduction algorithm to the rows section of
the Data View mapping table.
JSON
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
},
"dataReductionAlgorithm": {
"top": {
"count": 2000
}
}
}
}
}
]
You can apply the data reduction algorithm to the rows and columns sections of the
Data View mapping matrix.
Related content
Add drill-down support
Create custom Power BI visuals without data binding
Feedback
Was this page helpful? Yes No
This article describes the different options available for to specifying the way a visual
sorts items in Power BI.
By default, a visual doesn't support modifying its sorting order, unless stated otherwise
in the capabilities.json file.
default
implicit
custom
Default sorting
The default option is the simplest form. It allows the user to sort according to any one
field and direction (ascending or descending). The user selects the direction and field
from the more options menu.
To enable default sorting, add the following code to your capabilities.json file:
JSON
"sorting": {
"default": { }
}
Implicit sorting
Implicit sorting allows you to pre-define a sorting array using parameter clauses , that
describes sorting for each data role. The user can't change the sorting order, so Power BI
doesn't display sorting options in the visual's menu. However, Power BI does sort data
according to specified settings.
To enable implicit sorting, add the implicit clauses to your capabilities.json file clauses
parameters can contain several objects with two parameters each:
JSON
"sorting": {
"implicit": {
"clauses": [
{
"role": "category",
"direction": 1
},
{
"role": "measure",
"direction": 2
}
]
}
}
Custom sorting
Custom sorting gives the developer more flexibility when sorting. The developer can:
TypeScript
"sorting": {
"custom": {}
}
let queryName1 =
this.dataView.matrix.columns.levels[0].sources[0].queryName;
let queryName2 =
this.dataView.matrix.columns.levels[1].sources[0].queryName;
let args: CustomVisualApplyCustomSortArgs = {
sortDescriptors: [
{
queryName: queryName1,
sortDirection: powerbi.SortDirection.Ascending
},
{
queryName: queryName2,
sortDirection: powerbi.SortDirection.Descending
},
]
};
this.host.applyCustomSort(args);
Related content
Understand data view mapping in Power BI visuals
Understanding capabilities
Feedback
Was this page helpful? Yes No
To use the Authentication API, the ISV must first register an application in Microsoft
Entra ID for each cloud to be supported, and preauthorize the Power BI applications
with a dedicated scope for each visual. The tenant administrator then needs to grant
consent. This article outlines all of these essential steps.
4. Once your application is successfully registered, select Expose an API on the left
side menu.
7 Note
The application URI can be manually added to the application manifest under
the “identifierUris” array.
7. Select + Add a scope.
8. In the Scope name field, enter <visual_guid>_CV_ForPBI and add the required
information. Fill in the Admin consent fields. Then select Add scope button.
(There's a 40 characters scope length limitation, but you can manually modify the
scope name in the registered application manifest to manage this limitation).
b. Enter the Power BI WFE application appId in the Client ID field of the right-
hand window.
Power BI Desktop:
COM (required) and CN: "7f67af8a-fedc-4b08-8b4e-37c4d127b6cf".
GCC, GCCHIGH, and DOD: “6807062e-abc9-480a-ae93-9f7deee6b470".
Power BI Mobile:
COM (required) and CN: "c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12".
GCC, GCCHIGH and DOD: “ce76e270-35f5-4bea-94ff-eab975103dc6".
ISV consent
The tenant administrator can determine whether or not users are allowed to consent for
themselves. This consent process takes place outside of Power BI.
If the ISV application is running on a different tenant than the visual consumer's tenant,
grant consent for the ISV's application in one of the following ways:
Administrator preconsent:
{clientId}
CN: https://login.partner.microsoftonline.cn/{organization}/adminconsent?
client_id={clientId}
{clientId}
Interactive consent:
If the tenant administrator didn't preconsent, any user that uses a visual that
triggers the API receives a one-time consent prompt when rendering the visual.
See Application consent experience for more information.
Related content
Authentication API
Feedback
Was this page helpful? Yes No
Provide product feedback | Ask the community
Objects and properties of Power BI
visuals
Article • 10/11/2023
Objects describe customizable properties that are associated with a visual. An object can
have multiple properties, and each property has an associated type that describes what
the property will be. This article provides information about objects and property types.
myCustomObject is the internal name that's used to reference the object within dataView .
JSON
"objects": {
"myCustomObject": {
"properties": { ... }
}
}
7 Note
Display name and description are deprecated from API version 5.1+. The display
name and description are now added in the formatting model instead of the
capabilities.json file.
displayName is the name that will be shown in the property pane. description is a
description of the formatting property that will be shown to the user as a tooltip.
Properties
properties is a map of properties that are defined by the developer.
JSON
"properties": {
"myFirstProperty": {
"type": ValueTypeDescriptor | StructuralTypeDescriptor
}
}
7 Note
Example:
JSON
"properties": {
"show": {
"type": {"bool": true}
}
}
Property types
There are two property types: ValueTypeDescriptor and StructuralTypeDescriptor .
object.
TypeScript
TypeScript
Gradient property
The gradient property is a property that can't be set as a standard property. Instead, you
need to set a rule for the substitution of the color picker property (fill type).
JSON
"properties": {
"showAllDataPoints": {
"type": {
"bool": true
}
},
"fill": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"fillRule": {
"type": {
"fillRule": {}
},
"rule": {
"inputRole": "Gradient",
"output": {
"property": "fill",
"selector": [
"Category"
]
}
}
}
}
Pay attention to the fill and fillRule properties. The first is the color picker, and the
second is the substitution rule for the gradient that will replace the fill property,
visually , when the rule conditions are met.
This link between the fill property and the substitution rule is set in the
"rule" > "output" section of the fillRule property.
"Rule" > "InputRole" property sets which data role triggers the rule (condition). In this
example, if data role "Gradient" contains data, the rule is applied for the "fill"
property.
An example of the data role that triggers the fill rule ( the last item ) is shown in the
following code:
JSON
{
"dataRoles": [
{
"name": "Category",
"kind": "Grouping",
"displayName": "Details",
"displayNameKey": "Role_DisplayName_Details"
},
{
"name": "Series",
"kind": "Grouping",
"displayName": "Legend",
"displayNameKey": "Role_DisplayName_Legend"
},
{
"name": "Gradient",
"kind": "Measure",
"displayName": "Color saturation",
"displayNameKey": "Role_DisplayName_Gradient"
}
]
}
Formatting pane
To customize the properties in the formatting pane, use one of the following methods,
depending on what API version you're using.
7 Note
This method builds and returns a formatting model that includes full properties
pane hierarchy of formatting cards, formatting groups, Also it contains formatting
properties and their values.
For the following formatting property in the formatting model (See the descriptor
object content):
TypeScript
The corresponding object from the capabilities objects section should be:
JSON
"objects": {
"myCustomObject": {
"properties": {
"myCustomProperty": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
}
}
Example
The above myCustomCard example shows what formatting property in formatting
model would look like for an object with one property myCustomProperty . This
property object bound statically to dataViews[index].metadata.objects . Selector in
descriptor can be changed accordingly to selector type you choose.
static
columns
selector
scope identity
static
selector: null
columns
This object is bound to columns with the matching QueryName .
TypeScript
selector: {
metadata: 'QueryName'
}
selector
This object is bound to the element that you created a selectionID for. In this example,
let's assume that we created selectionID s for some data points, and we're looping
through them.
TypeScript
Scope identity
This object is bound to particular values at the intersection of groups. For example, if
you have categories ["Jan", "Feb", "March", ...] and series ["Small", "Medium",
"Large"] , you might want to have an object at the intersection of values that match Feb
and Large . To accomplish this, you could get the DataViewScopeIdentity of both
columns, push them to variable identities , and use this syntax with the selector.
TypeScript
selector: {
data: <DataViewScopeIdentity[]>identities
}
Related content
Performance tips
Feedback
Was this page helpful? Yes No
This article covers techniques on how a developer can achieve high performance when
rendering their custom visuals.
No one wants a visual to take a long time to render. Getting the visual to render as
quickly as possible is critical when writing the code.
7 Note
As we continue to improve and enhance the platform, new versions of the API are
constantly being released. In order to get the most out of the Power BI visuals'
platform and feature set, we recommend that you keep up-to-date with the most
recent version. To find out which version you’re using, check the apiVersion in the
pbiviz.json file.
Here are some recommendations for achieving optimal performance for your custom
visual.
These third party resources can help you decrease your plugin size, by finding ways for
you to remove unused code or tree-shaking and code-splitting .
If possible, compare these measurements with those of a similar core visual to see if
there are parts that can be optimized.
For more information, see the Using the User Timing API .
The following web developer tools can also help measure your visual's
performance, but keep in mind that they profile Power BI as well:
Metrics
JavaScript profiler
Once you determined which parts of your visual need optimization, check out these tips.
Update messages
When you update the visual:
Don't rerender the entire visual if only some elements have changed. Render only
the necessary elements.
Store the data view passed on update. Render only the data points that are
different from the previous data view. If they haven't changed, there's no need to
rerender them.
Resizing is often done automatically by the browser and doesn't require an update
to the visual.
To make sure that your code is fast and doesn’t slow down the browser, keep DOM
access to a minimum.
For example:
Instead of:
JavaScript
Try:
JavaScript
For example:
Instead of:
JavaScript
Try:
Make the above example faster by using html() and building the list beforehand:
JavaScript
$('#list').html(list);
Reconsider JQuery
Limit JS frameworks and use native JS whenever possible to increase the available
bandwidth and lower your processing overhead. Doing this might also decrease
compatibility issues with older browsers.
Animation
Animation options
For repeated use of animations, consider using Canvas or WebGL instead of SVG.
Unlike SVG, with these options performance is determined by size rather than content.
Read more about the differences in SVG vs Canvas: How to Choose.
For example, learn how to avoid unnecessary canvas state changes by rendering by
color instead of position.
Animation functions
Use requestAnimationFrame to update your on-screen animations, so your animation
functions are called before the browser calls another repaint.
Animation loops
Does the animation loop redraw unchanged elements?
If so, it wastes time drawing elements that don’t change from frame-to-frame.
When you're animating static visualizations, it’s tempting to lump all the draw code into
one update function and repeatedly call it with new data for each iteration of the
animation loop.
Instead, consider using a visual constructor method to draw everything static. Then the
update function only needs to draw visualization elements that change.
Tip
Common issues
Text size calculation: When there are a lot of data points, don't waste time
calculating text size for each point. Calculate a few points and then estimate.
If some elements of the visual aren't seen in the display, there's not need to render
them.
Related content
Optimization guide for Power BI
Feedback
Was this page helpful? Yes No
Mobile devices allow users to connect to their data anytime and anywhere.
Power BI apps for Windows, iOS, and Android enable business users to have a
comprehensive view of their data that's always at their fingertips.
As a developer creating Power BI visuals, you must address the unique constraints of
each mobile device to reach as many users as possible and provide the best mobile
experience.
Required functionality
The following requirements are essential for developing mobile-friendly visuals:
Rendering
Interactivity
Mobile devices should have the same interactive functionality as desktop devices.
All events handled on desktop browsers must be supported, or have comparable
event handlers, on mobile devices.
For example, if a desktop visual supports multi-selection using the Ctrl key,
consider adding a similar event handler for mobile devices.
ノ Expand table
click click
mousemove touchmove
mousedown touchstart
Mouse event name Touch event name
mouseup touchend
mouseover touchmove
wheel N/A
7 Note
Not all mobile or touch screen devices support mouse (or mouse prefixed)
events. In unsupported cases, handle both mouse and touch events at the
same time.
Optional functionality
The following functions are optional. The optional functions can be used to create a
better end-user experience.
Recommended rendering
To support smaller visual sizes, add format options that allow the user to adjust the
size of each element. For example, add format options to labels to use in reports
and dashboards. The format options allow users to customize a visual specifically
for their mobile device.
The same settings can be applied to the visuals in desktop browsers and, if
needed, be overridden to adapt the visual to smaller screens.
7 Note
To optimize a visual in Focus mode, both portrait and landscape screen size
orientations should be considered. See Display content in Focus mode.
Recommended interactivity
If a visual can't render on a mobile device, the visual should show a descriptive
error.
Related content
Develop a Power BI circle card visual
Feedback
Was this page helpful? Yes No
This article describes some basic debugging procedures you can use when developing
your visual. After reading this article, you should be able use the following methods to
debug your visual:
Insert breakpoints
Catch exceptions
Log exceptions
Insert breakpoints
The visual's entire JavaScript is reloaded every time the visual is updated Therefore, any
breakpoints you add will be lost when the debug visual is refreshed. As a workaround,
use debugger statements in your code. It's recommended to turn off auto reload while
using debugger in your code. Here's an example of how to use a debugger statement in
your update method.
TypeScript
Catch exceptions
When working on your visual, you'll notice that all errors are 'consumed' by the Power BI
service. This is an intentional feature of Power BI. It prevents misbehaving visuals from
causing the entire app to become unstable.
As a workaround, add code to catch and log your exceptions, or set your debugger to
break on caught exceptions.
TypeScript
You can use this decorator on any function to see error logging as follows.
TypeScript
@logExceptions()
public update(options: VisualUpdateOptions) {
Break on exceptions
You can also set the browser to break on caught exceptions. Breaking stops code
execution wherever an error happens, and allows you to debug from there.
Microsoft Edge
3. Select the Pause on exceptions icon (stop sign with a pause symbol).
Feedback
Was this page helpful? Yes No
This article explains how to diagnose and fix the following common problems that can
occur when setting up your developer environment for creating custom Power BI visuals.
When you run pbiviz in your terminal's command line, you should see the help screen.
If you don't, make sure you have NodeJS version 4.0 or higher installed. For help with
installing pbiviz or NodeJS see Set up your environment for developing a Power BI
visual.
If the server's not running, your SSL certificates were probably not installed correctly. To
install your SSL certificates, see Create an SSL certificate.
If you don't see it, make sure you have enabled developer mode in the Power BI
settings.
7 Note
The developer visual is currently only available in the Power BI service and not in
Power BI Desktop or the mobile app. The packaged visual will work everywhere.
For customer experience issues when using custom Power BI visuals, submit a case
request via the Power Platform admin center portal .
Related content
Setting up your Power BI environment
Frequently asked questions about Power BI visuals
When you create a visual, sometimes it's useful to display additional information to the
customer in a separate window. For example, you might want to:
For these purposes, you can create a dialog visual pop-up window, called a dialog box in
this article.
During development, you can specify the size and position of the dialog box.
When the dialog box is triggered, the report background is grayed.
The dialog header contains the visual’s icon and its display name as a title.
The dialog box can have up to three action buttons. You can choose which buttons
to display from a given selection.
The dialog box uses a rich HTML iframe .
While the dialog box is displayed, no action can be performed in the report until
it's dismissed.
The dialog code can use external npm libraries, just like the visual.
) Important
The dialog box should not be triggered spontaneously. It should be the immediate
result of a user action.
An implementation file - It's best practice to create an implementation file for each
dialog box.
Code to invoke your dialog box - To invoke your dialog box, add code to the
visual.ts file.
Each dialog box implementation file should include the following components:
Create a dialog box class for your dialog box. The initialState parameter in
openModalDialog is passed to the dialog contractor upon its creation. Use the
initialState object to pass parameters to the dialog box, in order to affect its behavior
or appearance.
The dialog code can use these IDialogHost methods:
can programmatically close the dialog and provide a result object back to its
calling visual.
TypeScript
Console
Class realization:
TypeScript
document.addEventListener('keydown', e => {
if (e.code == 'Enter' && pickedDate) {
host.close(DialogAction.Close, {date: pickedDate});
}
});
}
}
TypeScript
JavaScript
Each dialog box you create needs to be invoked in the visual.ts file. In this example,
the dialog box is defined with two action buttons.
TypeScript
In this example, the dialog box is invoked by clicking a visual button. The visual button is
defined as part of the visual constructor in the visual.ts file.
TypeScript
The position parameter lets you decide where the dialog box should open on the
screen. You can choose to open the dialog box in the center of the screen, or you can
define a different position relative to the visual.
TypeScript
If no type is specified, the default behavior is to open the dialog box in the center.
The position is given in pixels relative to the top left corner of the visual.
This example shows a 250 x 300 pixel date selection dialog box 100 pixels to the left and
30 pixels below the top of the visual:
TypeScript
constructor(options: VisualConstructorOptions) {
this.host = options.host;
this.target = options.element;
const dialogActionsButtons = [DialogAction.OK, DialogAction.Cancel];
You can also program the dialog box to automatically close by calling the IDialogHost
close method. This method is blocked for five seconds after the dialog is opened, so
that the earliest you can automatically close the dialog box is five seconds after it was
initiated.
This blocking is in effect only for the current session. So if a user blocks the CV modal
dialogs but later changes their mind, they can re-enable the dialogs. To do it they need
to start a new session (refresh the reports page in Power BI service, or restart Power BI
Desktop).
The size limitations of the dialog box are described in the table below.
ノ Expand table
When defining the position of the dialog box, the horizontal position can be a
positive or negative integer, depending on which side of the visual you want the
box to be. The vertical position can't be negative, as this would place it above the
visual.
The following features don't support the Power BI visuals dialog box:
Embedded analytics
Publish to web
Dashboards
You can program your visual to detect if the current environment allows opening a
dialog box, by checking the boolean this.host.hostCapabilities.allowModalDialog .
Related content
Publish a Power BI custom visual
Feedback
Was this page helpful? Yes No
In a Power BI visual, a display warning icon can notify the user of a possible problem or
an error. Display warning icons can be useful in many cases, such as:
A map visual can display a warning icon when values are outside the latitude or
longitude valid range.
A pie chart visual can display a warning icon when it's displaying negative values
that are mixed with positive ones.
A cartesian chart can display a warning icon when infinity values are calculated. For
example, if Y is zero, when dividing X by Y, the result is infinity.
When the icon appears, the user can hover over it to see the title of the warning
message.
When the user selects the warning icon, a message that describes the problem appears
in a pop-up window.
Create a warning icon
You can create a warning icon with a customized message for a custom visual. The
decision whether to raise the warning icon or not is up to you. As these examples
demonstrate, the visual continues to function when the warning icon is displayed.
JavaScript
After you add the import, add a condition that determines when to display the warning
icon. Use the examples in this article to view two optional conditions.
In this example, the visual compares the language of the visual, which is set to US
English, to the language of the operating system. If the languages don't match, the
warning icon is displayed.
JavaScript
if (this.locale != 'en-US') {
The getColumnColorByIndex method iterates through all the columns. If two adjacent
columns have the same color, a warning icon is displayed.
JavaScript
if (color1 == color2) {
this.host.displayWarningIcon('Adjacent columns have the same
color.', 'Columns that are next to each other have the same color. To change
a column's color, use the data colors option in the Format tab.');
}
The display warning is cleared during each rendering of the visual, for example,
when new data is dragged into the visual. The visual's update() method is invoked
after the visual is rendered. If the visual's warning is raised based on a condition
that's checked in the update method, each time the visual is rendered, if the
condition is met, the visual displays the warning again.
Related content
DataViewUtils
Feedback
Was this page helpful? Yes No
Sometimes you want to allow the user to interact with the visual by selecting, zooming,
or clicking on it. Other times you want the visual to be static, so the user can't interact
with the visual.
Visuals can query the value of the allowInteractions flag, which indicates if the visual
allows visual interactions. For example, visuals can be interactive during report viewing
or editing, but visuals can be non-interactive when they're viewed in a dashboard. These
interactions include click, pan, zoom, selection, and others.
7 Note
Best practice is to enable tooltips in all scenarios, regardless of the indicated flag.
For any Power BI scenario that requires non-interactive visuals (for example, dashboard
tiles), set the allowInteractions flag to false . Otherwise (for example, Report), set
allowInteractions to true .
The following code sample shows how to use the allowInteractions flag to set
interactive permissions.
TypeScript
...
let allowInteractions = options.host.hostCapabilities.allowInteractions;
bars.on('click', function(d) {
if (allowInteractions) {
selectionManager.select(d.selectionId);
...
}
});
For more information about using the allowInteractions flag, see the SampleBarChart
visual repository .
Next steps
Visual API
Add interactivity into visual by Power BI
visuals selections
Article • 12/29/2023
Power BI provides two ways to interact with visuals - selecting and filtering. The
following example demonstrates how to select an item from one visual and notify the
other visuals in the report about the new selection state.
TypeScript
Select
Clear the selection
Show the context menu
Store the current selections
Check the selection state
TypeScript
TypeScript
This object has corresponding methods to create selections for different types of data
view mappings.
7 Note
The methods withTable and withMatrixNode were introduced on API 2.5.0 of the
Power BI visuals. If you need to use selections for table or matrix data view
mappings, update to API version 2.5.0 or higher.
ノ Expand table
GM Import Truck 0
JSON
{
"dataRoles": [
{
"displayName": "Columns",
"name": "columns",
"kind": "Grouping"
},
{
"displayName": "Rows",
"name": "rows",
"kind": "Grouping"
},
{
"displayName": "Values",
"name": "values",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "columns"
}
},
"values": {
"group": {
"by": "rows",
"select": [
{
"for": {
"in": "values"
}
}
]
}
}
}
}
]
}
In the preceding example, Manufacturer is columns and Type is rows . A series is created
by grouping values by rows ( Type ).
For example, if a user selects Chrysler by Manufacturer , other visuals should show the
following data:
ノ Expand table
When the user selects Import Car by Type (selects data by series), the other visuals
should show the following data:
ノ Expand table
In the preceding example, Manufacturer is category (columns), Type is series (rows), and
Sales is Values for series.
7 Note
Values are required for displaying a series because, according to the data view
TypeScript
// categories
const categories = dataView.categorical.categories;
In the preceding sample code, we iterate through all categories. In each iteration, we call
createSelectionIdBuilder to create the next selection for each category by calling the
withCategory method of the selection builder. The createSelectionId method is used
In the withCategory method, we pass the column of category , in the sample, its
Manufacturer , and the index of category element.
TypeScript
this.dataPoints.push({
value: ser.name,
selection: seriesSelectionId
});
JSON
{
"dataRoles": [
{
"displayName": "Values",
"name": "values",
"kind": "GroupingOrMeasure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
}
}
}
}
]
}
To create a selection for each row of table data view mapping, call the withTable
method of selection builder.
TypeScript
The visual code iterates the rows of the table and each row calls the withTable table
method. Parameters of the withTable method are the table object and the index of the
table row.
In the sample, nodeWalker recursively calls each node and child node.
TypeScript
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
TypeScript
interface ISelectionManager {
// ...
select(selectionId: ISelectionId | ISelectionId[], multiSelect?:
boolean): IPromise<ISelectionId[]>;
// ...
}
The select method can accept an array of selections. This allows your visual to have
several data points selected at once. The second parameter, multiSelect , is responsible
for multi-selections. If multiSelect is true, Power BI doesn't clear the previous selection
state when it applies the current selection. If the value is false, the previous selection is
overwritten.
A typical example of using multiSelect is handling the Ctrl button state on a click
event. When the Ctrl button is held down, you can select more than one object.
TypeScript
Related content
Handle selections on bookmarks switching
Feedback
Was this page helpful? Yes No
Tooltips are an elegant way of providing more contextual information and detail to data
points on a visual. The Power BI tooltips API can handle the following interactions:
Show a tooltip.
Hide a tooltip.
Move a tooltip.
Tooltips can display a textual element with a title, a value in a given color, and opacity at
a specified set of coordinates. This data is provided to the API, and the Power BI host
renders it the same way it renders tooltips for native visuals.
You can change the style of your tooltips or add drilling actions by enabling the modern
tooltips feature.
The above tooltip image illustrates a single bar category and value. You can extend the
tooltip to display multiple values.
Manage tooltips
You can manage the tooltips in your visual through the ITooltipService interface.
ITooltipService notifies the host that a tooltip needs to be displayed, removed, or
moved.
TypeScript
interface ITooltipService {
enabled(): boolean;
show(options: TooltipShowOptions): void;
move(options: TooltipMoveOptions): void;
hide(options: TooltipHideOptions): void;
}
Your visual should detect mouse events within the visual and call the show() , move() ,
and hide() delegates, as needed, with the appropriate content populated in the Tooltip
options objects. TooltipShowOptions and TooltipHideOptions in turn define what to
Calling these methods involves user events such as mouse moves and touch events, so
it's a good idea to create listeners for these events, which would in turn invoke the
TooltipService members. The following example aggregates in a class called
TooltipServiceWrapper .
The class holds and manages any relevant state and logic for these events, which are
mostly geared at interfacing with the underlying D3 code. The D3 interfacing and
conversion is out of scope for this article.
The example code in this article is based on the SampleBarChart visual . You can
examine the source code in barChart.ts.
Create TooltipServiceWrapper
The bar chart constructor now has a TooltipServiceWrapper member, which is
instantiated in the constructor with the host tooltipService instance.
TypeScript
this.tooltipServiceWrapper =
createTooltipServiceWrapper(this.host.tooltipService, options.element);
The TooltipServiceWrapper class holds the tooltipService instance, also as the root D3
element of the visual and touch parameters.
TypeScript
The single entry point for this class to register event listeners is the addTooltip method.
public addTooltip<T>(
selection: d3.Selection<Element>,
getTooltipInfoDelegate: (args: TooltipEventArgs<T>) =>
VisualTooltipDataItem[],
getDataPointIdentity: (args: TooltipEventArgs<T>) =>
ISelectionId,
reloadTooltipDataOnMouseMove?: boolean): void {
if (!selection || !this.visualHostTooltipService.enabled()) {
return;
}
...
...
}
As you can see, addTooltip exits with no action if the tooltipService is disabled or
there's no real selection.
TypeScript
...
...
selection.on("mouseover.tooltip", () => {
// Ignore mouseover while handling touch events
if (!this.canDisplayTooltip(d3.event))
return;
this.visualHostTooltipService.show({
coordinates: tooltipEventArgs.coordinates,
isTouchEvent: false,
dataItems: tooltipInfo,
identities: selectionId ? [selectionId] : [],
});
});
makeTooltipEventArgs: Extracts the context from the D3 selected elements into a
tooltipEventArgs. It calculates the coordinates as well.
getTooltipInfoDelegate: It then builds the tooltip content from the
tooltipEventArgs. It's a callback to the BarChart class, because it is the visual's logic.
It's the actual text content to display in the tooltip.
getDataPointIdentity: Unused in this sample.
this.visualHostTooltipService.show: The call to display the tooltip.
Additional handling can be found in the sample for mouseout and mousemove events.
TypeScript
In the preceding implementation, the header member is constant, but you can use it for
more complex implementations, which require dynamic values. You can populate the
VisualTooltipDataItem[] with more than one element, which adds multiple lines to the
tooltip. It can be useful in visuals such as stacked bar charts where the tooltip might
display data from more than a single data point.
TypeScript
this.tooltipServiceWrapper.addTooltip(this.barContainer.selectAll('.bar'),
(tooltipEvent: TooltipEventArgs<number>) =>
BarChart.getTooltipData(tooltipEvent.data),
(tooltipEvent: TooltipEventArgs<number>) => null);
For example:
JSON
{
"tooltips": {
"supportedTypes": {
"default": true,
"canvas": true
},
"roles": [
"tooltips"
]
}
}
You can then define the tooltips from the Formatting pane of the report page.
supported.
canvas : Specifies whether the report page tooltips are supported.
roles : (Optional) After it's defined, it instructs what data roles are bound to the
To display the report page tooltip, after the Power BI host calls
ITooltipService.Show(options: TooltipShowOptions) or ITooltipService.Move(options:
selected data (category, series, and so on) of the item you hovered over.
An example of sending the selectionId to tooltip display calls is shown in the following
code:
TypeScript
this.tooltipServiceWrapper.addTooltip(this.barContainer.selectAll('.bar'),
(tooltipEvent: TooltipEventArgs<number>) =>
BarChart.getTooltipData(tooltipEvent.data),
(tooltipEvent: TooltipEventArgs<number>) =>
tooltipEvent.data.selectionID);
For example:
JSON
{
"tooltips": {
... ,
"supportEnhancedTooltips": true
}
}
See an example of the modern tooltips feature being used in the SampleBarChart
code.
7 Note
Adding this feature to the capabilities.json file gives the user the possibility of
enabling this feature for the report. Keep in mind that the user will still have to
enable the modern tooltip feature in the report settings.
Related content
Tooltip utils
Feedback
Was this page helpful? Yes No
The Analytics pane allows you to add dynamic reference lines, like min, max, or average,
to your visuals. These lines can help you zoom in on important trends or insights. This
article discusses how to create Power BI visuals that can present and manage dynamic
reference lines in the Analytics pane.
7 Note
The Analytics pane is available in API version 2.5.0. To find out which version you’re
using, check the apiVersion in the pbiviz.json file.
API 5.1+
Under the object's definition, add only the object name, property name and type as
explained here. Example:
JSON
{
"objects": {
"YourAnalyticsPropertiesCard": {
"properties": {
"show": {
"type": {
"bool": true
}
},
"displayName": {
"type": {
"text": true
}
},
... //any other properties for your Analytics card
}
}
...
}
}
In the formatting settings card, specify that this card belongs to the analytics pane by
setting the set card analyticsPane parameter to true . By default, analyticsPane
parameter is false and the card will be added to formatting pane. See the following
implementations:
Define other properties the same way that you do for Format objects, and enumerate
objects just as you do in the Format pane.
7 Note
Use the Analytics pane only for objects that add new information or shed new
light on the presented information (for example, dynamic reference lines that
illustrate important trends).
Any options that control the look and feel of the visual (that is, formatting)
should be limited to the Formatting pane.
Feedback
Was this page helpful? Yes No
Starting from API version 5.1, developers can create visuals that use the new Power
format pane. Developers can define the cards and their categories for any property in
their custom visual, making it easier for report creators to use these visuals.
The new API uses the FormattingModel method to customize parts of the format and
analytics panes.
Tip
In addition to all the old formatting pane capabilities, the new formatting model
supports new format pane capabilities, new properties and new hierarchies.
To upgrade to API version 5.1+, set the apiVersion in your pbiviz.json file to 5.1 or later
and do one of the following:
object name
property name
property type
All other properties, including DisplayName and description , are now optional.
2. Build the custom visual FormattingModel. Define the properties of your custom
visual formatting model and build it using code (not JSON).
3. Implement the getFormattingModel API in the custom visual class that returns
custom visual formatting model. (This API replaces the enumerateObjectInstances
that was used in previous versions).
2. For each object name and property name in capabilities.json, create a matching
formatting property. The formatting property should have a descriptor that
contains an objectName and propertyName that matches the object name and
property name in capabilities.json.
The objects properties in the capabilities file still have the same format and don't need
to be changed.
For example, if the circle object in your capabilities.json file is defined like this:
JSON
"objects": {
"circle": {
"properties": {
"circleColor": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
}
}
}
The formatting property in your model should be of type ColorPicker and look like this:
JavaScript
control: {
type: "ColorPicker",
properties: {
descriptor: {
objectName: "circle",
propertyName: "circleColor"
},
value: {
value: this.visualSettings.circle.circleColor
}
}
}
The object or property name in the capabilities file doesn’t match the one in the
formatting model
The property type in the capabilities file doesn’t match the type in formatting
model
Formatting model
The formatting model is where you describe and customize all the properties of your
format pane.
Formatting model
The largest pane container, used for formatting the pane's frontal interface. It
contains a list of formatting cards.
Formatting card
The top level properties grouping container for formatting properties. Each card
consists of one or more formatting groups, as shown here.
Formatting group
The secondary-level properties grouping container. The formatting group is
displayed as a grouping container for formatting slices.
Formatting slice
Property container. There are two types of slices:
Simple slice: Individual property container
Composite slice: Multiple related property containers grouped into one
formatting slice
The following image shows the different types of slices. "Font" is a composite slice
consisting of font family, size, and bold, italics and underline switches. "Color",
"display units" and the other slices are simple slices with one component each.
Visualization pane formatting properties
Every property in the formatting model should match and object type in the
capabilities.json file.
The following table shows the formatting property types in capabilities.json file and their
matching type class in modern formatting model properties:
ノ Expand table
ノ Expand table
*
The enumeration list formatting property is different in the formatting model and in
the capabilities file.
Declare the following properties in the formatting settings class, including the list
of enumeration items:
ItemDropdown
ItemFlagsSelection
Declare the following properties in the formatting settings class, without the list of
enumeration items. Declare their enumeration items list in capabilities.json under
the appropriate object. (These types are the same as in the previous API versions):
AutoDropdown
AutoFlagSelection
FontControl
This keeps all font related properties together. It consists of the following
properties:
Font Family
Font Size
Bold [optional]
Italic [optional]
Underline [optional]
ノ Expand table
MarginPadding Margin padding determines the alignment of the text in the visual.
It consists of the following properties:
Left
Right
Top
Bottom
ノ Expand table
JSON
"objects": {
"dataCard": {
"properties": {
"displayUnitsProperty": {
"type":
{
"formatting": {
"labelDisplayUnits": true
}
}
},
"fontSize": {
"type": {
"formatting": {
"fontSize": true
}
}
},
"fontFamily": {
"type": {
"formatting": {
"fontFamily": true
}
}
},
"fontBold": {
"type": {
"bool": true
}
},
"fontUnderline": {
"type": {
"bool": true
}
},
"fontItalic": {
"type": {
"bool": true
}
},
"fontColor": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"lineAlignment": {
"type": {
"formatting": {
"alignment": true
}
}
}
}
}
}
TypeScript
To enable this feature, add a list of formatting card properties descriptors to formatting
card revertToDefaultDescriptors . The following the example shows how to add the
reset to default button:
TypeScript
revertToDefaultDescriptors: [
{
objectName: "dataCard",
propertyName:"displayUnitsProperty"
},
{
objectName: "dataCard",
propertyName: "fontFamily"
},
Localization
For more about the localization feature and to set up a localization environment see
Add the local language to your Power BI visual Use the localization manager to format
components that you want to localize:
TypeScript
displayName: this.localization.getDisplayName("Font_Color_DisplayNameKey");
description: this.localization.getDisplayName("Font_Color_DescriptionKey");
GitHub Resources
All formatting model interfaces can be found in GitHub - microsoft/powerbi-
visuals-api: Power BI custom visuals API in “formatting-model-api.d.ts”
We recommend using the new formatting model utils at GitHub -
microsoft/powerbi-visuals-utils-formattingmodel: Power BI visuals formatting
model helper utils
You can find an example of a custom visual SampleBarChart that uses API version
5.1.0 and implements getFormattingModel using the new formatting model utils at
GitHub - microsoft/PowerBI-visuals-sampleBarChart: Bar Chart Custom Visual for
tutorial .
Related content
More questions? Ask the Power BI Community
Feedback
Was this page helpful? Yes No
The fetchMoreData API lets you load data chunks of different sizes as a way of enabling
Power BI visuals to bypass the hard limit of a 30K row data view. In addition to the
original approach of aggregating all requested chunks, the API now also supports
loading data chunks incrementally.
You can configure the number of rows to fetch at a time in advance, or you can use
dataReductionCustomization to allow the report author set the chunk size dynamically.
7 Note
To find out which version you’re using, check the apiVersion in the pbiviz.json file.
For example, add the following code in the capabilities.json file to append 100 rows of
data at a time:
TypeScript
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
},
"dataReductionAlgorithm": {
"window": {
"count": 100
}
}
}
}
]
New segments are appended to the existing dataview and provided to the visual as an
update call.
You can determine whether data exists by checking for the existence of
dataView.metadata.segment :
TypeScript
You also can check to see whether the update is the first update or a subsequent update
by checking options.operationKind . In the following code,
VisualDataChangeOperationKind.Create refers to the first segment and
TypeScript
// CV update implementation
public update(options: VisualUpdateOptions) {
// indicates this is the first segment of new data.
if (options.operationKind == VisualDataChangeOperationKind.Create) {
You also can invoke the fetchMoreData method from a UI event handler:
TypeScript
btn_click(){
{
// check if more data is expected for the current data view
if (dataView.metadata.segment) {
// request for more data if available; as a response, Power BI will
call update method
let request_accepted: bool = this.host.fetchMoreData(true);
// handle rejection
if (!request_accepted) {
// for example, when the 100 MB limit has been reached
}
}
}
7 Note
To avoid client memory constraints, Power BI limits the fetched data total to 100
MB. When this limit is reached, fetchMoreData() returns false .
You can determine whether data exists by checking for the existence of
dataView.metadata.segment :
TypeScript
You also can check if the update is the first update or a subsequent update by checking
options.operationKind . In the following code, VisualDataChangeOperationKind.Create
TypeScript
// CV update implementation
public update(options: VisualUpdateOptions) {
// indicates this is the first segment of new data.
if (options.operationKind == VisualDataChangeOperationKind.Create) {
}
// complete update implementation
}
You also can invoke the fetchMoreData method from a UI event handler:
TypeScript
btn_click(){
{
// check if more data is expected for the current data view
if (dataView.metadata.segment) {
// request for more data if available; as a response, Power BI will
call update method
let request_accepted: bool = this.host.fetchMoreData(false);
// handle rejection
if (!request_accepted) {
// for example, when the 100 MB limit has been reached
}
}
}
7 Note
Although the data in the different updates of the data views are mostly exclusive,
there is some overlap between consecutive data views.
For table and categorical data mapping, the first N data view rows can be expected
to contain data copied from the previous data view.
dataView.table['lastMergeIndex'] + 1
The visual keeps the data view passed to it so it can access the data without extra
communications with Power BI.
JSON
"objects": {
"dataReductionCustomization": {
"displayName": "Data Reduction",
"properties": {
"rowCount": {
"type": {
"numeric": true
},
"displayName": "Row Reduction",
"description": "Show Reduction for all row groups",
"suppressFormatPainterCopy": true
},
"columnCount": {
"type": {
"numeric": true
},
"displayName": "Column Reduction",
"description": "Show Reduction for all column groups",
"suppressFormatPainterCopy": true
}
}
}
},
JSON
"dataReductionCustomization": {
"matrix": {
"rowCount": {
"propertyIdentifier": {
"objectName": "dataReductionCustomization",
"propertyName": "rowCount"
},
"defaultValue": "100"
},
"columnCount": {
"propertyIdentifier": {
"objectName": "dataReductionCustomization",
"propertyName": "columnCount"
},
"defaultValue": "10"
}
}
}
The data reduction information appears under visual in the format pane.
The data view memory size is limited to 100 MB In segments aggregation mode.
Related content
Data view mappings
DataViewUtils
Feedback
Was this page helpful? Yes No
With Power BI report bookmarks, you can capture and save a configured view of a
report page. Then you can go back to the saved view quickly and easily whenever you
want. The bookmark saves the entire configuration, including selections and filters.
For more information about bookmarks, see Use bookmarks to share insights and build
stories in Power BI.
7 Note
Visual API version 1.11.0 or later for non-filter visuals that use
SelectionManager .
First, select one or more data points in your visual. The visual passes your selections to
the host. Then select Add in the Bookmark pane. Power BI saves the current selections
for the new bookmark.
Do this several times to create new bookmarks. After you create the bookmarks, you can
switch between them.
Each time you select a bookmark, Power BI restores the saved filter or selection state
and passes it to the visuals. The visuals in the report are highlighted or filtered
according to the state stored in the bookmark. To restore the correct state, your visual
must pass the correct selection state to the host (for example, the colors of rendered
data points).
The new selection state (or filter) is communicated through the options.jsonFilters
property in the update method. The jsonFilters can be either Advanced Filter or Tuple
Filter.
If your visual contains selected data points, reset the selection to that of the
selected bookmark by using the callback function, registerOnSelectCallback , in
ISelectionManager .
If your visual uses filters to select data, reset the filter values to the corresponding
values of the selected bookmark.
7 Note
If your visual interacts with other visuals using Selection , you can add bookmark
support in one of two ways:
Through SelectionManager.
When you select a bookmark, the utility automatically handles the visual's selection
state.
Use SelectionManager to restore bookmark selections
You can save and recall bookmark selections using the
ISelectionManager.registerOnSelectCallback method as follows:
When you select a bookmark, Power BI calls the callback method of the visual with the
corresponding selections.
TypeScript
this.selectionManager.registerOnSelectCallback(
(ids: ISelectionId[]) => {
//called when a selection was set by Power BI
});
);
Let's assume you created a data point in the visualTransform method of your visual.
TypeScript
visualDataPoints.push({
category: categorical.categories[0].values[i],
color: getCategoricalObjectValue<Fill>(categorical.categories[0], i,
'colorSelector', 'fill', defaultColor).solid.color,
selectionId: host.createSelectionIdBuilder()
.withCategory(categorical.categories[0], i)
.createSelectionId(),
selected: false
});
You now have visualDataPoints as your data points and the ids array passed to the
callback function.
At this point, the visual should compare the ISelectionId[] array with the selections in
your visualDataPoints array, and then mark the corresponding data points as selected.
TypeScript
this.selectionManager.registerOnSelectCallback(
(ids: ISelectionId[]) => {
visualDataPoints.forEach(dataPoint => {
ids.forEach(bookmarkSelection => {
if (bookmarkSelection.equals(dataPoint.selectionId)) {
dataPoint.selected = true;
}
});
});
});
);
After you update the data points, they'll reflect the current selection state stored in the
filter object. Then, when the data points are rendered, the custom visual's selection
The visual creates an advanced filter and calls the host method applyJsonFilter to filter
data by the relevant conditions.
TypeScript
this.host.applyJsonFilter(
filter,
"general",
"filter",
(startDate && endDate)
? FilterAction.merge
: FilterAction.remove
);
Each time you select a bookmark, the custom visual gets an update call.
In the update method, the visual checks the filter in the object:
TypeScript
If the filter object isn't null, the visual restores the filter conditions from the object:
TypeScript
if (jsonFilters
&& jsonFilters[0]
&& jsonFilters[0].conditions
&& jsonFilters[0].conditions[0]
&& jsonFilters[0].conditions[1]
) {
const startDate: Date = new
Date(`${jsonFilters[0].conditions[0].value}`);
const endDate: Date = new Date(`${jsonFilters[0].conditions[1].value}`);
After that, the visual changes its internal state to match the current conditions. The
internal state includes the data points and visualization objects (lines, rectangles, and so
on).
The Timeline Slicer visual changes the range selector to the corresponding data ranges.
For example, the Timeline Slicer stores the Granularity property values as a filter
state. It allows the granularity of the timeline (days, months, years, etc.) to change as you
change bookmarks.
The filterState property saves a filter aspect as a property. The visual can store various
filterState values in bookmarks.
To save a property value as a filter state, set the object property as "filterState": true
in the capabilities.json file.
Related content
What are bookmarks
Create bookmarks in desktop reports
Feedback
Was this page helpful? Yes No
Every Power BI visual can display a context menu. The context menu allows you to
perform various operations on the visual, such as analyzing, summarizing, or copying it.
When you right-click anywhere inside a visual's viewport (or long-press for touch
devices), the context menu displays. There are two modes of context menus for each
visual. The mode that displays depends on where you click inside the visual:
Call the context menu on empty space to see the basic context menu for the
visual.
Call the context menu on a specific data point for added options that can be
applied to that data point. In this case, the context menu also contains the options
Show data point as a table, Include, and Exclude, which will apply the corresponding
filter to that data point.
7 Note
The following example shows how to add a context menu to a visual. The code is taken
from the barChart.ts file, which is part of the sample BarChart visual :
TypeScript
constructor(options: VisualConstructorOptions) {
...
this.handleContextMenu();
}
private handleContextMenu() {
this.rootSelection.on('contextmenu', (event: PointerEvent,
dataPoint) => {
this.selectionManager.showContextMenu(dataPoint ? dataPoint: {},
{
x: mouseEvent.clientX,
y: mouseEvent.clientY
});
mouseEvent.preventDefault();
});
}
Related content
Add interactivity into visual by Power BI visuals selections
Build a bar chart
Feedback
Was this page helpful? Yes No
From API version 4.2, developers can create reports with dynamic string formats
support.
JSON
"objects": {
"general": {
"properties": {
"formatString": {
"type": {
"formatting": {
"formatString": true
}
}
}
}
},
}
Feedback
Was this page helpful? Yes No
Provide product feedback | Ask the community
Add drill-down support
Article • 12/19/2023
When a visual has a hierarchy, you can allow users to use the Power BI drill-down
feature to reveal more details.
Read more about the Power BI drill-down feature at Drill mode in the Power BI service.
To allows the visual to enable or disable the drill feature dynamically, see Dynamic drill-
down control.
JSON
"drilldown": {
"roles": [
"category"
]
}
7 Note
The drill-down dataRole must be of Grouping type. max property in the dataRole
conditions must be set to 1.
Once you add the role to the drill-down field, users can drag multiple fields into the
data role.
For example:
JSON
{
"dataRoles": [
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"drilldown": {
"roles": [
"category"
]
},
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "value"
}
}
]
}
}
}
]
}
To create a default sample visual, apply the above sample of capabilities.json to the
newly created visual.
Create the property for div container to hold HTML elements of the visual:
TypeScript
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// imports
constructor(options: VisualConstructorOptions) {
// constructor body
// ...
}
/**
* Returns properties pane formatting model content hierarchies,
properties and latest formatting values, Then populate properties pane.
* This method is called once each time we open the properties pane or
when the user edits any format property.
*/
public getFormattingModel(): powerbi.visuals.FormattingModel {
return
this.formattingSettingsService.buildFormattingModel(this.formattingSettings)
;
}
}
TypeScript
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.formattingSettingsService = new FormattingSettingsService();
this.target = options.element;
this.updateCount = 0;
if (document) {
const new_p: HTMLElement = document.createElement("p");
new_p.appendChild(document.createTextNode("Update count:"));
const new_em: HTMLElement = document.createElement("em");
this.textNode =
document.createTextNode(this.updateCount.toString());
new_em.appendChild(this.textNode);
new_p.appendChild(new_em);
this.div = document.createElement("div"); // <== CREATE DIV
ELEMENT
this.target.appendChild(new_p);
}
}
}
TypeScript
}
// ...
less
button {
margin: 5px;
min-width: 50px;
min-height: 50px;
}
ノ Expand table
H1 H2 H3 VALUES
A A1 A11 1
A A1 A12 2
A A2 A21 3
A A2 A22 4
A A3 A31 5
A A3 A32 6
B B1 B11 7
B B1 B12 8
B B2 B21 9
B B2 B22 10
B B3 B31 11
B B3 B32 12
Save host object in the properties of the visual and call createSelectionManager
method to the create selection manager to display a context menu by using Power BI
Visuals API.
TypeScript
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// default imports
constructor(options: VisualConstructorOptions) {
// constructor body
// save the host in the visuals properties
this.host = options.host;
// create selection manager
this.selectionManager = this.host.createSelectionManager();
// ...
}
// ...
}
TypeScript
categoricalDataView.categories[categoricalDataView.categories.length -
1].values.forEach( (category: powerbi.PrimitiveValue, index: number) => {
// create selectionID for each category value
let selectionID: ISelectionId = this.host.createSelectionIdBuilder()
.withCategory(categoricalDataView.categories[0], index)
.createSelectionId();
this.div.appendChild(button);
});
ノ Expand table
JSON
{
"dataRoles": [
{
"displayName": "Columns",
"name": "columns",
"kind": "Grouping"
},
{
"displayName": "Rows",
"name": "rows",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"drilldown": {
"roles": [
"columns",
"rows"
]
},
"dataViewMappings": [
{
"matrix": {
"columns": {
"for": {
"in": "columns"
}
},
"rows": {
"for": {
"in": "rows"
}
},
"values": {
"for": {
"in": "value"
}
}
}
}
]
}
TypeScript
// ...
import DataViewMatrix = powerbi.DataViewMatrix;
import DataViewMatrixNode = powerbi.DataViewMatrixNode;
import DataViewHierarchyLevel = powerbi.DataViewHierarchyLevel;
// ...
Create two properties for two div s of rows and columns elements:
TypeScript
this.colsDiv = document.createElement("div");
this.target.appendChild(this.colsDiv);
}
// ...
}
Check the data before rendering elements and display the current level of hierarchy:
TypeScript
TypeScript
// traversing rows
const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
rowRoot.children.forEach((node, index) => treeWalker(node, index,
matrixDataView.rows.levels, this.rowsDiv));
// traversing columns
const colRoot = matrixDataView.columns.root;
colRoot.children.forEach((node, index) => treeWalker(node, index,
matrixDataView.columns.levels, this.colsDiv));
}
// ...
}
TypeScript
Create buttons to interact with visual and display context menu for matrix datapoints:
TypeScript
div.appendChild(button);
if (matrixNode.children) {
// ...
}
}
TypeScript
while (this.colsDiv.firstChild) {
this.colsDiv.removeChild(this.colsDiv.firstChild);
}
// create label for columns elements
const pcol = document.createElement("p");
pcol.innerText = "Columns";
this.colsDiv.appendChild(pcol);
Related content
How to use the drill down support API
Dynamic drill-down control
Add colors to your Power BI visuals
Article • 01/10/2024
This article describes how to add colors to your custom visuals and how to handle data
points for a visual that has defined colors.
IVisualHost, the collection of properties and services that interact with the visual host,
can define colors in custom visuals with the colorPalette service. The example code in
this article modifies the SampleBarChart visual . For the SampleBarChart visual source
code, see barChart.ts .
To get started creating visuals, see Developing a a Power BI circle card visual.
TypeScript
/**
* Interface for BarChart data points.
*
* @interface
* @property {number} value - Data value for point.
* @property {string} category - Corresponding category of data value.
* @property {string} color - Color corresponding to data point.
*/
interface BarChartDataPoint {
value: number;
category: string;
color: string;
};
Define the color palette in the update method with the following code:
TypeScript
constructor(options: VisualConstructorOptions) {
this.host = options.host; // host: IVisualHost
...
}
TypeScript
Then, apply the data from dataPoints to the d3 -selection barSelection inside the
update method:
TypeScript
// This code is for d3 v5
// in d3 v5 for this case we should use merge() after enter() and apply
changes on barSelectionMerged
this.barSelection = this.barContainer
.selectAll('.bar')
.data(this.barDataPoints);
barSelectionMerged.classed('bar', true);
barSelectionMerged
.attr("width", xScale.bandwidth())
.attr("height", d => height - yScale(<number>d.value))
.attr("y", d => yScale(<number>d.value))
.attr("x", d => xScale(d.category))
.style("fill", (dataPoint: BarChartDataPoint) => dataPoint.color)
.style("stroke", (dataPoint: BarChartDataPoint) => dataPoint.strokeColor)
.style("stroke-width", (dataPoint: BarChartDataPoint) =>
`${dataPoint.strokeWidth}px`);
this.barSelection
.exit()
.remove();
Related content
Capabilities and properties of Power BI visuals.
How to debug Power BI visuals
Feedback
Was this page helpful? Yes No
Conditional formatting lets a report creator specify how colors are displayed in a report,
according to a numerical value.
This article describes how to add the conditional formatting functionality to your Power
BI visual.
Color
Text
Icon
Web URL
TypeScript
TypeScript
import VisualEnumerationInstanceKinds =
powerbiVisualsApi.VisualEnumerationInstanceKinds;
To format properties that support conditional formatting, set the required instance
kind in their descriptor .
TypeScript
Make the following changes to the properties you want to apply conditional formatting
to:
Add the altConstantValueSelector property with the value previously defined for
the selector property.
For formatting properties that support conditional formatting, set the required
instance kind in their descriptor .
TypeScript
formattingGroup.slices.push(
{
uid: `colorSelector${barDataPoint_indx}_uid`,
displayName: barDataPoint.category,
control: {
type: powerbi.visuals.FormattingComponent.ColorPicker,
properties: {
descriptor: {
objectName: "colorSelector",
propertyName: "fill",
// Define whether the conditional formatting
will apply to instances, totals, or both
selector:
dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataVie
wWildcardMatchingOption.InstancesAndTotals),
instanceKind:
powerbi.VisualEnumerationInstanceKinds.ConstantOrRule
},
value: { value: barDataPoint.color }
}
}
}
);
// ...
}
We recommend that you don’t use conditional formatting with series. Instead, you
should allow customers to format each series individually, making it easy to visually
distinguish between series. Most out-of-the-box visuals with series, share this approach.
Related content
DataViewUtils
Feedback
Was this page helpful? Yes No
By default, when an element is selected, the values array in the dataView object is
filtered to only show the selected values. When the values array is filtered, all other
visuals on the page only show the selected data.
No highlight support
Without highlight support, the selection is the only value in the values array and
the only bar presented in the data view.
With highlight support, all values are in the values array. The highlights array
contains a null value for non-highlighted elements. All bars appear in the data
view, and the highlighted bar is a different color.
There can also be multiple selections and partial highlights. The highlighted values are
presented in the data view.
7 Note
JSON
{
"dataRoles": [
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"for": {
"in": "value"
}
}
}
}
],
"supportsHighlight": true
}
After you remove unnecessary code, the default visual source code looks like the
following example:
TypeScript
"use strict";
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.formattingSettingsService = new FormattingSettingsService();
this.target = options.element;
this.host = options.host;
}
TypeScript
TypeScript
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.formattingSettingsService = new FormattingSettingsService();
this.target = options.element;
this.host = options.host;
}
// ...
}
Clear the contents of the div elements before rendering new data:
TypeScript
// ...
public update(options: VisualUpdateOptions) {
this.formattingSettings =
this.formattingSettingsService.populateFormattingSettingsModel(VisualFormatt
ingSettingsModel, options.dataViews);
console.log('Visual update', options);
while (this.div.firstChild) {
this.div.removeChild(this.div.firstChild);
}
// ...
}
Get the categories and measure values from the dataView object:
TypeScript
public update(options: VisualUpdateOptions) {
this.formattingSettings =
this.formattingSettingsService.populateFormattingSettingsModel(VisualFormatt
ingSettingsModel, options.dataViews);
console.log('Visual update', options);
while (this.div.firstChild) {
this.div.removeChild(this.div.firstChild);
}
7 Note
Enumerate the categoryValues array and get corresponding values and highlights:
TypeScript
// ...
const measureHighlights = measures.highlights;
});
Create div and p elements to display and visualize data view values in the visual DOM:
TypeScript
div.appendChild(barValue);
barValue.appendChild(barHighlight);
div.appendChild(p);
});
Apply the required styles for elements to use flexbox , and define colors for div
elements:
css
div.vertical {
display: flex;
flex-direction: column;
}
div.horizontal {
display: flex;
flex-direction: row;
}
div.highlight {
background-color: blue
}
div.value {
background-color: red;
display: flex;
}
JSON
{
"dataRoles": [
{
"displayName": "Columns",
"name": "columns",
"kind": "Grouping"
},
{
"displayName": "Rows",
"name": "rows",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"matrix": {
"columns": {
"for": {
"in": "columns"
}
},
"rows": {
"for": {
"in": "rows"
}
},
"values": {
"for": {
"in": "value"
}
}
}
}
],
"supportsHighlight": true
}
The sample data to create a hierarchy for matrix data view mapping:
ノ Expand table
Create the default visual project, and apply the sample of the capabilities.json file.
After you remove the unnecessary code, the default visual source code looks like the
following example:
TypeScript
"use strict";
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.formattingSettingsService = new FormattingSettingsService();
this.target = options.element;
this.host = options.host;
}
/**
* Returns properties pane formatting model content hierarchies,
properties and latest formatting values, Then populate properties pane.
* This method is called once every time we open properties pane or when
the user edit any format property.
*/
public getFormattingModel(): powerbi.visuals.FormattingModel {
return
this.formattingSettingsService.buildFormattingModel(this.formattingSettings)
;
}
}
TypeScript
TypeScript
constructor(options: VisualConstructorOptions) {
// ...
this.rowsDiv = document.createElement("div");
this.target.appendChild(this.rowsDiv);
this.colsDiv = document.createElement("div");
this.target.appendChild(this.colsDiv);
this.target.style.overflowY = "auto";
}
Check the data in the update method to ensure that the visual gets data:
TypeScript
if (!matrixDataView ||
!matrixDataView.columns ||
!matrixDataView.rows ) {
return
}
// ...
}
Clear the contents of the div elements before rendering new data:
TypeScript
while (this.colsDiv.firstChild) {
this.colsDiv.removeChild(this.colsDiv.firstChild);
}
const pcol = document.createElement("p");
pcol.innerText = "Columns";
this.colsDiv.appendChild(pcol);
// ...
}
TypeScript
public update(options: VisualUpdateOptions) {
// ...
const treeWalker = (matrixNode: DataViewMatrixNode, index: number,
levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
}
// ...
}
Where matrixNode is the current node, levels is metadata columns of this hierarchy
level, div - parent element for child HTML elements.
The treeWalker is the recursive function, need to create div element and p for text as
header, and call the function for child elements of node:
TypeScript
if (matrixNode.children) {
const childDiv = document.createElement("div");
childDiv.classList.add("vertical");
div.appendChild(childDiv);
const p = document.createElement("p");
const level = levels[matrixNode.level]; // get current level
column metadata from current node
p.innerText = level.sources[level.sources.length -
1].displayName; // get column name from metadata
Call the function for root elements of the column and row of the matrix data view
structure:
TypeScript
// ...
const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
rowRoot.children.forEach((node) => treeWalker(node,
matrixDataView.rows.levels, this.rowsDiv));
TypeScript
The object of terminal node has two properties for the values array, value and highlight:
JavaScript
JSON.stringify(options.dataViews[0].matrix.rows.root.children[0].children[0]
.children[0], null, " ");
JSON
{
"level": 2,
"levelValues": [
{
"value": "R233",
"levelSourceIndex": 0
}
],
"value": "R233",
"identity": {
"identityIndex": 2
},
"values": {
"0": {
"value": null,
"highlight": null
},
"1": {
"value": 19,
"highlight": 19
}
}
}
Where value represents the value of the node without applying a selection from the
other visual, highlight indicates which part of the data was highlighted.
7 Note
If the value of highlight is less than the value of value , then value was partially
highlighted.
Add code to process the values array of the node if it's presented:
TypeScript
public update(options: VisualUpdateOptions) {
// ...
const treeWalker = (matrixNode: DataViewMatrixNode, index: number,
levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// ...
if (matrixNode.values) {
const sumOfValues = Object.keys(matrixNode.values) // get key
property of object (value are 0 to N)
.map(key => +matrixNode.values[key].value) // convert key
property to number
.reduce((prev, curr) => prev + curr) // sum of values
if (matrixNode.children) {
// ...
}
}
// ...
}
The result is a visual with buttons and values, like highlighted value/default value .
Related content
Matrix data mappings
Add interactivity into visual by Power BI visuals selections
Feedback
Was this page helpful? Yes No
The supportsMultiVisualSelection feature enables you to select values from one visual
in a Power BI report and apply the selected values to all the visuals in that report.
1. Select the Total Sales Variance %, Sales Per Sq Ft and This Year Sales by District
and District visual. In the Filters pane that appears, under Chain, select Fashions
Direct.
2. Select the Total Sales Variance by FiscalMonth and District Manager visual. In the
Filters pane that appears, under FiscalMonth, select Jan.
In the report, these selections apply to all visuals that support this feature. The scope of
the visuals is now limited to Fashions Direct and January.
JSON
{
...
"supportsMultiVisualSelection": true
...
}
Feedback
Was this page helpful? Yes No
This article explains how to support navigation through a Power BI visual using the
keyboard. Keyboard navigation makes Power BI more accessible to people with
disabilities and provides more options for interacting with reports.
The supportsKeyboardFocus feature makes it possible to navigate the data points of the
visual by using only the keyboard.
Press Esc to move the focus from inside the visual to the visual container.
Press Tab from inside a custom visual to navigate through tabbable elements in
the visual. Pressing Tab after the last tababble element moves the focus back
outside of the visual.
JSON
{
...
"supportsKeyboardFocus": true
...
}
Press Enter when the focus is on the visual container to move the focus to inside
the custom visual.
Press Tab from inside the custom visual to navigate through tabbable elements.
The focus stays inside the visual until you press Esc .
7 Note
Not all HTML elements are tabbable by default (for example, div and span).
Consider adding the correct attribute (e.g tabindex) to these elements to make
them tabbable.
Pressing Enter on the visual container won't always land on the first focusable
element of the visual. To be sure to start at the first element, focus it
programmatically after the focus goes into the visual.
After pressing Enter on the visual container and after pressing Tab on the last
focusable element, the user might have to press Tab more than once to get to the
first element.
Related content
Design Power BI reports for accessibility
Developing a Power BI circle card visual
Feedback
Was this page helpful? Yes No
The Windows high-contrast setting makes text and graphics easier to see by displaying
more distinct colors. This article discusses how to add high-contrast mode support to
Power BI visuals. For more information, see High-contrast support in Power BI.
Initialization
The colorPalette member of options.host has several properties for high-contrast
mode. Use these properties to determine whether high-contrast mode is active and, if it
is, what colors to use.
When displaying in high-contrast mode, your visual should limit itself to the
following settings:
Foreground color is used to draw any lines, icons, text, and outline or fill of
shapes.
Background color is used for background, and as the fill color of outlined
shapes.
If a secondary color is needed, the foreground color can be used with some
opacity (Power BI native visuals use 40% opacity). Use this sparingly to
keep the visual details easy to see.
During initialization, you can store the following values in your constructor method:
TypeScript
constructor(options: VisualConstructorOptions) {
this.host = options.host;
let colorPalette: ISandboxExtendedColorPalette = host.colorPalette;
//...
this.isHighContrast = colorPalette.isHighContrast;
if (this.isHighContrast) {
this.foregroundColor = colorPalette.foreground.value;
this.backgroundColor = colorPalette.background.value;
this.foregroundSelectedColor =
colorPalette.foregroundSelected.value;
this.hyperlinkColor = colorPalette.hyperlink.value;
}
Or, you can store the host object during initialization and access the relevant
colorPalette properties during an update.
Implementation
The specific implementations of high-contrast support vary from visual to visual and
depend on the details of the graphic design. To keep important details easy to
distinguish with limited colors, high-contrast mode ordinarily requires a design that's
slightly different from the default mode.
The following sample bar chart is drawn with two pixels of thick foreground outline and
background fill. Compare the way it looks with default colors and with the following
high-contrast themes:
Standard colors
Example
The following code shows one place in the visualTransform function that was changed
to support high-contrast. It's called as part of rendering during the update. For the full
implementation of this code, see the barChart.ts file in the PowerBI-visuals-
sampleBarChart visual repository .
No high-contrast support
TypeScript
barChartDataPoints.push({
category: category.values[i] + '',
value: dataValue.values[i],
color: getCategoricalObjectValue<Fill>(category, i,
'colorSelector', 'fill', defaultColor).solid.color,
selectionId: host.createSelectionIdBuilder()
.withCategory(category, i)
.createSelectionId()
});
}
Related content
Design Power BI reports for accessibility
Feedback
Was this page helpful? Yes No
Slicers are a useful way to filter information and focus on a specific portion of the
semantic model. They allow you to select exactly which values to display in your Power
BI visual.
Sometimes you might want to use a slicer on only one specific page of the report. Other
times, you might want to apply the slicer to several pages. By using the sync slicers
feature, a slicer selection on any page will affect visualizations on all selected pages.
For information about sync slicers and how they work, see Sync and use slicers on other
pages.
JSON
{
...
"supportsHighlight": true,
"suppressDefaultTitle": true,
"supportsSynchronizingFilterState": true,
"sorting": {
"default": {}
}
}
After you've updated the capabilities.json file, you can view the Sync slicers pane when
you select your custom slicer visual.
From the Sync slicers pane, you can select which report pages the slicer visibility and
filtration should apply to.
For more information on how to sync slicers, see Sync and use slicers on other pages.
7 Note
A report using the sync slicers feature must use API version 1.13.0 or later.
Related content
Add a context menu to your Power BI visual
Request aggregated subtotal data
Article • 11/22/2023
The Total and Subtotal API allows custom visuals with a matrix data-view to request
aggregated subtotal data from the Power BI host. The subtotals are calculated for the
entire matrix semantic model or specified for individual levels of the matrix data
hierarchy. See the sample report for an example of the Total and Subtotal API in a
Power BI visual.
7 Note
Every time a visual refreshes its data, the visual issues a data fetch request to the Power
BI backend. These data requests are usually for values of the fields that the user dragged
into the field wells of the visual. Sometimes the visual needs other aggregations or
subtotals (for example, sum or count) applied to the field wells. The Total and Subtotal
API lets you customize the outgoing data query to request more aggregation or
subtotal data.
row or column. Unlike all the other properties, this property is applied to individual
rows or columns.
rowSubtotalsType : ("Top" or "Bottom") Indicates if the row with the total data
should be retrieved before ( top ) or after ( bottom ) the rest of the data. If this
property is set to bottom , the total can only be displayed after all the data has
been fetched. The default is bottom .
Each of the previously listed switches is assigned a value based on the related properties
in the property pane and the defaults.
specify the property that each of the above switches maps to.
provide the default value to be used if the property is undefined.
JSON
"rowSubtotals": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "rowSubtotals"
},
"defaultValue": true
},
The preceding code indicates that the row subtotals are enabled by the property
rowSubtotals in the subTotals object. The property has a default value of true .
The API is automatically enabled for a visual whenever the subtotals structure and all
switch mappings are defined in the capabilities.json file.
The following code is an example of the complete API configuration in the
capabilities.json file (copied from the API sample visual):
JSON
"subtotals": {
"matrix": {
"rowSubtotals": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "rowSubtotals"
},
"defaultValue": true
},
"rowSubtotalsPerLevel": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "perRowLevel"
},
"defaultValue": false
},
"columnSubtotals": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "columnSubtotals"
},
"defaultValue": true
},
"columnSubtotalsPerLevel": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "perColumnLevel"
},
"defaultValue": false
},
"levelSubtotalEnabled": {
"propertyIdentifier": {
"objectName": "subTotals",
"propertyName": "levelSubtotalEnabled"
},
"defaultValue": true
},
"rowSubtotalsType": {
"propertyIdentifier": {
"objectName": "subtotals",
"propertyName": "rowSubtotalsType"
},
"defaultValue": "Bottom"
}
}
}
It's important that the enumerateProperties() function of the visual aligns with the
defaults specified in the capabilities.json file. The customization logic operates according
to the specified defaults. If the enumerateProperties() function and the defaults aren't
aligned, the actual subtotal customizations might differ from user expectations.
TypeScript
enum RowSubtotalType {
Top = "Top",
Bottom = "Bottom",
}
To review the available customizations, expand the Subtotals drop-down menu in the
Format property pane. Modify the subtotals settings and track the changes to the
subtotals presentation (named Totals) in the Visualizations pane.
Related content
Add interactivity to visual using Power BI visuals selections
Feedback
Was this page helpful? Yes No
This article explains how to use the No data binding feature to create Power BI custom
visuals without data roles. Ordinarily, when you create a visual in a Power BI report, the
values are defined interactively by adding data fields to the Values well on the
Visualizations pane.
By default, if no values are defined, the format settings are disabled, and you can't
update the visual's formatting.
The dataRoles property of the capabilities model allows you to format graphics in
Power BI without binding data.
Using the dataRoles capabilities property, you can render a visual and use the update
method to change the format settings. You can change settings even if the data buckets
are empty, or if your visual doesn't use any data roles.
The following tabs show two examples of a Power BI visual. One visual requires binding
data, and the other uses the no data roles feature and doesn't require binding data.
7 Note
This feature is available from API version 3.6.0 and above. To find out which version
you’re using, check the apiVersion in the pbiviz.json file.
To enable the No data binding feature, set the following two parameters in the
capabilities.json file to true .
JSON
{
"supportsLandingPage": true,
"supportsEmptyDataView": true,
}
Related content
Using capabilities
Add a landing page
Feedback
Was this page helpful? Yes No
Power BI supports a range of local languages. You can retrieve the Power BI locale
language, and use it to display content in your visual.
The following tabs show examples of the same sample bar chart visual displaying
content in different languages. Each of these bar charts was created using a different
locale language (English, Basque, and Hindi) which is displayed in the tooltip.
7 Note
The localization manager in the visual's code is supported from API 1.10.0 and
higher.
Localization is not supported for debugging the visual while in development.
Power BI service - If you're using Power BI service (web portal), change your
language in settings:
1. Sign in to PowerBI.com .
>
TypeScript
7 Note
In Power BI Desktop, the locale property contains the language of the installed
Power BI Desktop.
JSON
{
"dataRoles": [
{
"displayName": "Category Data",
"displayNameKey": "VisualCategoryDataNameKey1",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure Data",
"displayNameKey": "VisualMeasureDataNameKey2",
"name": "measure",
"kind": "Measure"
}
]
}
Examples
resources.resjson file with Russian strings for each displayNameKey .
JSON
{
...
"Role_Legend": "Обозначения",
"Role_task": "Задача",
"Role_StartDate": "Дата начала",
"Role_Duration": "Длительность"
...
}
{
...
"Role_Legend": ""מקרא,
"Role_task": ""משימה,
"Role_StartDate": ""תאריך התחלה,
"Role_Duration": ""משך זמן
...
}
TypeScript
constructor(options: VisualConstructorOptions) {
this.localizationManager = options.host.createLocalizationManager();
}
For example, the following code returns Legend for en-US, and Обозначения for ru-RU.
TypeScript
7 Note
TypeScript
displayName: this.localization.getDisplayName("Font_Color_DisplayNameKey");
description: this.localization.getDisplayName("Font_Color_DescriptionKey");
Supported languages
The following table contains a list of all the languages supported in Power BI, and the
string that the locale variable returns for each one.
ノ Expand table
ar-SA ( العربيةArabic)
he-IL ( עבריתHebrew)
zh-CN 中国 (Chinese-Simplified)
zh-TW 中國 (Chinese-Tranditional)
Related content
Formatting utils
Feedback
Was this page helpful? Yes No
This article describes the basics of writing unit tests for your Power BI visuals, including
how to:
Prerequisites
An installed Power BI visuals project
A configured Node.js environment
The examples in this article use the bar chart visual for testing.
JSON
"@types/d3": "5.7.2",
"@types/d3-selection": "^1.0.0",
"@types/jasmine": "^3.10.2",
"@types/jasmine-jquery": "^1.5.34",
"@types/jquery": "^3.5.8",
"@types/karma": "^6.3.1",
"@types/lodash-es": "^4.17.5",
"coveralls": "^3.1.1",
"d3": "5.12.0",
"jasmine": "^3.10.0",
"jasmine-core": "^3.10.1",
"jasmine-jquery": "^2.1.1",
"jquery": "^3.6.0",
"karma": "^6.3.9",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^4.0.1",
"karma-junit-reporter": "^2.0.1",
"karma-sourcemap-loader": "^0.3.8",
"karma-typescript": "^5.5.2",
"karma-typescript-preprocessor": "^0.4.0",
"karma-webpack": "^5.0.0",
"powerbi-visuals-api": "^3.8.4",
"powerbi-visuals-tools": "^3.3.2",
"powerbi-visuals-utils-dataviewutils": "^2.4.1",
"powerbi-visuals-utils-formattingutils": "^4.7.1",
"powerbi-visuals-utils-interactivityutils": "^5.7.1",
"powerbi-visuals-utils-tooltiputils": "^2.5.2",
"puppeteer": "^11.0.0",
"style-loader": "^3.3.1",
"ts-loader": "~8.2.0",
"ts-node": "^10.4.0",
"tslint": "^5.20.1",
"tslint-microsoft-contrib": "^6.2.0"
Save the package.json file and run the following command at the location of the
package.json file:
npm install
The package manager installs all new packages that are added to package.json.
To run unit tests, configure the test runner and the webpack config.
TypeScript
module.exports = {
devtool: 'source-map',
mode: 'development',
optimization : {
concatenateModules: false,
minimize: false
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.tsx?$/i,
enforce: 'post',
include: /(src)/,
exclude: /(node_modules|resources\/js\/vendor)/,
loader: 'istanbul-instrumenter-loader',
options: { esModules: true }
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'less-loader',
options: {
paths: [path.resolve(__dirname, 'node_modules')]
}
}
]
}
]
},
externals: {
"powerbi-visuals-api": '{}'
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.css']
},
output: {
path: path.resolve(__dirname, ".tmp/test")
},
plugins: [
new webpack.ProvidePlugin({
'powerbi-visuals-api': null
})
]
};
TypeScript
"use strict";
const webpackConfig = require("./test.webpack.config.js");
const tsconfig = require("./test.tsconfig.json");
const path = require("path");
process.env.CHROME_BIN = require("puppeteer").executablePath();
srcCssRecursivePath : Locates the output CSS after compiling less file with styles.
singleRun: true : Tests are run on a continuous integration (CI) system, or they can
be run one time. You can change the setting to false for debugging your tests.
The Karma framework keeps the browser running so that you can use the console
for debugging.
files: [...] : In this array, you can specify the files to load to the browser. The
files you load are typically source files, test cases, and libraries (such as Jasmine or
test utilities). You can add more files as necessary.
preprocessors : In this section, you configure actions that run before the unit tests
run. The actions can precompile TypeScript to JavaScript, prepare source map files,
and generate a code coverage report. You can disable coverage when you debug
your tests. coverage generates more code for code coverage testing, which
complicates debugging tests.
For descriptions of all Karma configurations, go to the Karma Configuration File page.
For your convenience, you can add a test command into scripts in package.json:
JSON
{
"scripts": {
"pbiviz": "pbiviz",
"start": "pbiviz start",
"typings":"node node_modules/typings/dist/bin.js i",
"lint": "tslint -r \"node_modules/tslint-microsoft-contrib\" \"+
(src|test)/**/*.ts\"",
"pretest": "pbiviz package --resources --no-minify --no-pbiviz --no-
plugin",
"test": "karma start"
}
...
}
TypeScript
The build method creates an instance of your visual. mainElement is a get method,
which returns an instance of a root document object model (DOM) element in your
visual. The getter is optional, but it makes writing the unit test easier.
You now have a build of an instance of your visual. Let's write the test case. The example
test case checks the SVG elements that are created when your visual is displayed.
TypeScript
describe("BarChart", () => {
let visualBuilder: BarChartBuilder;
let dataView: DataView;
let defaultDataViewBuilder: SampleBarChartDataBuilder;
beforeEach(() => {
visualBuilder = new BarChartBuilder(500, 500);
defaultDataViewBuilder = new SampleBarChartDataBuilder();
dataView = defaultDataViewBuilder.getDataView();
});
beforeEach : Is called before each call of the it method, which is defined in the
describe method.
toBeInDOM : Is one of the matchers methods. For more information about matchers,
For more information about Jasmine, see the Jasmine framework documentation
page.
7 Note
TypeScript
return dataView;
}
}
The SampleBarChartDataBuilder class extends TestDataViewBuilder and implements the
abstract method getDataView .
When you put data into data-field buckets, Power BI produces a categorical dataview
object that's based on your data.
In unit tests, you don't have access to Power BI core functions that you normally use to
reproduce the data. But you need to map your static data to the categorical dataview .
Use the TestDataViewBuilder class to map your static data.
JSON
"dataRoles": [
{
"displayName": "Category Data",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure Data",
"name": "measure",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"category": {
"max": 1
},
"measure": {
"max": 1
}
}
],
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
}
}
],
To generate the same mapping, you must set the following parameters to the
createCategoricalDataViewBuilder method:
TypeScript
([
{
source: {
displayName: "Category",
queryName: SampleBarChartDataBuilder.CategoryColumn,
type: ValueType.fromDescriptor({ text: true }),
roles: {
Category: true
},
},
values: this.valuesCategory
}
],
[
{
source: {
displayName: "Measure",
isMeasure: true,
queryName: SampleBarChartDataBuilder.MeasureColumn,
type: ValueType.fromDescriptor({ numeric: true }),
roles: {
Measure: true
},
},
values: this.valuesMeasure
},
], columnNames)
ts
ts
ts
return dataView;
}
}
Now, you can use the SampleBarChartDataBuilder class in your unit test.
JSON
"powerbi-visuals-utils-testutils": "^2.4.1",
Call
npm install
Now, you can run the unit test again. You must get the following output:
The summary shows that coverage has increased. To learn more about current code
coverage, open the coverage/html-report/index.html file.
Or look at the scope of the src folder:
In the file scope, you can view the source code. The coverage utilities highlight the row
in red if certain lines of code don't run during the unit tests.
) Important
Code coverage doesn't mean that you have good functionality coverage of the
visual. One simple unit test provides over 96 percent coverage in src/barChart.ts .
Debugging
To debug your tests via browser console, change the singleRun value in karma.conf.ts to
false . This setting will keep your browser running when the browser launches after the
tests run.
Related content
When your visual is ready, you can submit it for publication. For more information, see
Publish Power BI visuals to AppSource.
Feedback
Was this page helpful? Yes No
Advanced edit mode enables you to use advanced UI controls in your Power BI visual.
From report editing mode, select the Edit button on a visual and set the edit mode to
Advanced. The visual uses the EditMode flag to determine if it should display this UI
control.
0 - NotSupported. The visual doesn't support Advanced edit mode. The Edit
require any further changes. Power BI doesn't switch the visual to Focus Mode.
Developers can use this setting as an external button to run several processes in
the same viewport.
2 - SupportedInFocus. The visual supports Advanced edit mode and requires the
When you select Edit, the visual gets an update() call with EditMode set to Advanced .
Depending on the value that's set in the capabilities.json file, the following actions occur:
Related content
Add conditional formatting
Feedback
Was this page helpful? Yes No
Before you can load your custom visual into Power BI Desktop or share it with the
community in the Power BI Visual Gallery , you need to package it. Using this tutorial,
you will:
2. In VS Code, navigate to the root folder of your visual project and open the
pbiviz.json file.
3. In the visual object, set the displayName value to what you want to be your
visual's display name.
The visual's display name appears in the Visualizations pane of Power BI when you
hover the cursor over the visual icon.
visualClassName
description
command to run.
5. Fill in supportUrl and gitHubUrl with the URLs that a user can visit to get support
and view your visual's GitHub project.
{
"supportUrl": "https://community.powerbi.com",
"gitHubUrl": "https://github.com/microsoft/PowerBI-visuals-
circlecard"
}
2. In Windows Explorer, copy the icon.png file you want to use, and then paste it to
replace the default icon.png file located in the assets folder.
3. In VS Code, in the Explorer pane, expand the assets folder, and then select the
icon.png file.
PowerShell
pbiviz package
This command creates a pbiviz file in the /dist/ directory of your visual project, and
overwrites any previous pbiviz file that might exist.
The package outputs to the /dist/ folder of the project. The package contains everything
required to import the custom visual into either the Power BI service or a Power BI
Desktop report. You packaged the custom visual, and it's ready for use.
Related content
Publish Power BI visuals to Partner Center
Feedback
Was this page helpful? Yes No
Before you publish your visual to AppSource , it must pass the tests listed in this
article. It's important to test your visual before you submit it. If your visual doesn't pass
the required test cases, it will be rejected.
For more information about the publishing process, see Publish Power BI visuals to
Partner Center.
When testing or updating a visual that's already published, make sure you're using the
correct version of the visual without changing the GUID. To override the AppSource
version with a local file version, enable Developer mode in either Power BI Desktop or
Power BI service.
) Important
To enable Developer mode in Power BI service, follow the instructions in Set up Power BI
service for developing a visual.
ノ Expand table
Test case Expected results
Create a Stacked column chart with No error appears after these conversions.
Category and Value. Convert it to your
visual and then back to column chart.
Create a Gauge with three measures. No error appears after these conversions.
Convert it to your visual and then back to
Gauge.
Select elements in other visuals. Your visual shows filtered data according to
selection in other visuals.
Check min/max dataViewMapping Field buckets can accept multiple fields, a single
conditions. field, or are determined by other buckets. The
min/max dataViewMapping conditions must be
correctly set up in the capabilities of your visual.
Remove all fields in different orders. Visual cleans up properly as fields are removed in
arbitrary order. There are no errors in the console
or the browser.
Open the Format pane with each possible This test doesn't trigger null reference exceptions.
bucket configuration.
Filter data using the Filter pane at the visual, Tooltips are correct after applying filters. Tooltips
page, and report level. show the filtered value.
Filter data using a Slicer. Tooltips are correct after applying filters. Tooltips
show the filtered value.
Filter data using a published visual. For Tooltips are correct after applying filters. Tooltips
instance, select a pie slice or a column. show the filtered value.
If cross-filtering is supported, verify that Applied selection filters other visuals on this page
filters work correctly. of the report.
Select with Ctrl , Alt , and Shift keys. No unexpected behaviors appear.
Change the View Mode to Actual size, Fit to Mouse coordinates are accurate.
page, and Fit to width.
Ensure scroll bars work correctly. Scroll bars should exist, if necessary. Check scroll
bar sizes. Scroll bars shouldn't be too wide or tall.
Position and size of scroll bars must be in accord
with other elements of your visual. Verify that
Test case Expected results
Add multiple versions of your visual to a All versions of the visual display and operate
single report page. properly.
Add multiple versions of your visual to All versions of the visual display and operate
multiple report pages. properly.
Test Reading view and Edit view for your All functions work correctly.
visual.
If your visual uses animations, add, change, Animation of visual elements works correctly.
and delete elements of your visual.
Open the Property pane. Turn properties on The visual responds correctly.
and off, enter custom text, stress the options
available, and input bad data.
Save the report and reopen it. All properties settings persist.
Switch pages in the report and then switch All properties settings persist.
back.
Test all functionality of your visual, including All displays and features work correctly.
different options that the visual provides.
Test all numeric, date, and character data All data is formatted properly.
types, as in the following tests.
Review formatting of tooltip values, axis All elements are formatted correctly.
labels, data labels, and other visual elements
with formatting.
Verify that data labels use the format string. All data labels are formatted correctly.
Switch automatic formatting on and off for Tooltips display values correctly.
numeric values in tooltips.
Test data entries with different types of data, All displays and features work correctly.
including numeric, text, date-time, and
different format strings from the model. Test
different data volumes, such as thousands of
rows, one row, and two rows.
Provide bad data to your visual, such as null, All displays and features work correctly.
infinity, negative values, and wrong value
Test case Expected results
types.
ノ Expand table
Windows
Google Chrome (previous version) All displays and features work correctly.
Mozilla Firefox (previous version) All displays and features work correctly.
Microsoft Edge (previous version) All displays and features work correctly.
Microsoft Internet Explorer 11 (optional) All displays and features work correctly.
macOS
Linux
Firefox (latest and previous versions) All displays and features work correctly.
Mobile iOS
Apple Safari iPad (previous Safari version) All displays and features work correctly.
Chrome iPad (latest Safari version) All displays and features work correctly.
Mobile Android
Chrome (latest and previous versions) All displays and features work correctly.
Desktop testing
Test your visual in the current version of Power BI Desktop .
ノ Expand table
Import, save, open a file, and publish to the Power BI web service by All displays and features
using the Publish button in Power BI Desktop. work correctly.
Change the numeric format string to have zero decimal places or three The visual displays
decimal places by increasing or decreasing the precision. correctly.
Performance testing
Your visual should perform at an acceptable level. Use developer tools to validate its
performance. Don't rely on visual cues and the console time logs.
ノ Expand table
Create a visual with The visual should perform well and not freeze the application. There should
many visual be no performance issues with elements such as animation speed, resizing,
elements. filtering, and selecting. Check out these tips for optimal performance.
Related content
Publish Power BI visuals to Partner Center
Get a Power BI visual certified
Performance tips for creating quality Power BI custom visuals
Feedback
Was this page helpful? Yes No
Once you have created your Power BI visual, you may want to publish it to AppSource
for others to discover and use. For a detailed explanation of how to create a Power BI
visual offer, see Plan a Power BI visual offer.
What is AppSource?
AppSource is the place to find SaaS apps and add-ins for your Microsoft products and
services. You can find many Power BI visuals here.
Prerequisite
To submit your Power BI visual, you must be enrolled with Partner Center. If you're not
yet enrolled, Open a developer account in Partner Center.
) Important
If you're resubmitting or updating a visual, do not change its GUID. Follow these
instructions to test a new version of a visual.
When you're ready to submit your Power BI visual, verify that your visual meets all the
following requirements.
ノ Expand table
Pbiviz package Yes Pack your Power BI visual into a .pbiviz package. Ensure the
pbiviz.json file contains all the required metadata:
- Visual name
- Display name
- GUID
- Version (four digits: x.x.x.x )
- Description
- Support URL
- Author name and email
Sample .pbix Yes To help users become familiar with the visual, highlight the value
report file that the visual brings to the user and give examples of usage and
formatting. You can also add a "hints" page at the end with some
tips and tricks and things to avoid.
The sample .pbix report file must work offline, without any
external connections.
Logo Yes Include the custom visual logo that will appear in the
Marketplace listing. It should be in PNG format and exactly 300 x
300 px.
Important! Review the AppSource store images guide carefully,
before submitting the logo.
Screenshots Yes Provide at least one screenshot, and up to five, in PNG format.
The dimensions must be exactly 1366 px (width) by 768 px
(height), and the size not larger than 1024 kb.
Add text bubbles to explain the value of key features shown in
each screenshot.
Support Yes Provide a support URL for your customers. This link is entered as
download link part of your Partner Center listing, and is visible to users when
they access your visual's listing on AppSource. The URL should
start with https://.
Privacy Yes Provide a link to the visual's privacy policy. This link is entered as
document link part of your Partner Center listing, and is visible to users when
they access your visual's listing on AppSource. The URL should
start with https://.
Item Required Description
End-user license Yes You must provide an EULA file for your Power BI visual. You can
agreement use the standard contract , Power BI visuals contract , or your
(EULA) own EULA.
Video link No To increase the interest of users for your custom visual, provide a
link to a video about your visual. The URL should start with
https://.
Before you create the .pbiviz package, complete the following fields in the pbiviz.json
file:
description
supportUrl
author
name
email
7 Note
Individual publishers can use one of these methods to submit a Power BI visual:
If you have an old Seller Dashboard account, you can continue using this
account's credentials to sign into Partner Center.
If you don't have an old Seller Dashboard account, and are not registered to
Partner Center, you'll need to Open a developer account in Partner Center
using your work email.
) Important
Before you submit your visual, make sure it passes all the requirements. A visual
that doesn't pass the requirements will be rejected.
When you're ready to create or update your offer, follow the instructions in Create a
Power BI app offer.
Related content
Performance tips for creating quality Power BI custom visuals
Guidelines for publishing Power BI visuals
Test your Power BI visual before submitting for certification
Feedback
Was this page helpful? Yes No
Certified Power BI visuals are Power BI visuals in AppSource that meet the Microsoft
Power BI team code requirements and testing. The tests performed are designed to
check that the visual doesn't access external services or resources. However, Microsoft
isn't the author of third-party custom visuals, and we advise customers to contact the
author directly to verify the functionality of these visuals.
Certified Power BI visuals can be used like any other Power BI visual. They offer more
features than noncertified visuals. For example, you can export them to PowerPoint, or
display the visual in received emails when a user subscribes to report pages.
The certification process is optional. It's up to the developers to decide if they want their
visual certified. Power BI visuals that aren't certified, aren't necessarily unsafe. Some
Power BI visuals aren't certified because they don't comply with one or more of the
certification requirements. For example, a map Power BI visual connecting to an external
service, or a Power BI visual using commercial libraries can't be certified.
Removal of certification
Microsoft reserves the right to remove a visual from the certified list, at its discretion.
Certification requirements
To get your Power BI visual certified, it must meet the requirements listed in this section.
General requirements
Your Power BI visual has to be approved by Partner Center. Before requesting
certification, we recommend that you publish your Power BI visual in AppSource . To
learn how to publish a Power BI visual to AppSource, see Publish Power BI visuals to
Partner Center.
Code for only one Power BI visual. It can't contain code for multiple Power BI
visuals, or unrelated code.
A branch named certification (lowercase required). The source code in this branch
has to match the submitted package. This code can only be updated during the
next submission process, if you're resubmitting your Power BI visual.
If your Power BI visual uses private npm packages, or git submodules, you must also
provide access to the repositories containing this code.
To understand how a Power BI visual repository looks, review the GitHub repository for
the Power BI visuals sample bar chart .
File requirements
Use the latest version of the API to write the Power BI visual.
.gitignore - Add node_modules , .tmp and, dist to this file. The code can't include
the node_modules, .tmp, or dist folders.
capabilities.json - If you're submitting a newer version of an existing Power BI
visual with changes to the properties in this file, verify that they don't break reports
for existing users.
pbiviz.json
package.json. The visual must have the following package installed:
"typescript"
"eslint"
"eslint-plugin-powerbi-visuals"
The file must contain a command for running linter - "eslint": "npx eslint . -
-ext .js,.jsx,.ts,.tsx"
package-lock.json
tsconfig.json
Command requirements
Make sure that the following commands don't return any errors.
npm install
pbiviz package
npm audit - Must not return any warnings with high or moderate level.
ESlint with the required configuration . This command must not return any lint
errors.
7 Note
We're in the process of migrating from TSlint to ESLint. Visuals using TSlint will
be accepted for certification until March 2023. After that, ESlint will be
required.
Compiling requirements
Use the latest version of powerbi-visuals-tools to write the Power BI visual.
Compile your Power BI visual with pbiviz package . If you're using your own build
scripts, provide a npm run package custom build command.
Follow the code requirements listed here to make sure that your code is in line with the
Power BI certification policies.
Required
user data.
Minified JavaScript files or projects.
Tip
The Power BI certification process might take time. If you're creating a new Power
BI visual, we recommend that you publish your Power BI visual via the Partner
Center before you request Power BI certification. This ensures that the publishing of
your visual is not delayed.
When the Power BI visual card is clicked in AppSource, a yellow badge titled PBI
Certified indicates that this Power BI visual is certified.
You can display only certified Power BI visuals, by selecting the Power BI Certified
filter option.
Publication timeline
The process of deploying to AppSource can take time. Your Power BI visual will be
available to download from AppSource when this process is complete.
7 Note
The version field in AppSource will be updated with the day your Power BI was
approved by AppSource, approximately a week after you submitted your
visual. Users will be able to download the updated visual but the updated
capabilities will not take effect. Your visual's new capabilities will affect the
user's reports after about a two weeks.
Related content
Frequently asked questions about certified visuals.
Guidelines for publishing Power BI visuals
Before you publish Power BI custom visuals to Microsoft commercial marketplace for
others to discover and use, follow these guidelines to create a great experience for your
users.
Like the free Power BI visuals, an IAP Power BI visual can also be certified. Before
submitting your IAP Power BI visual for certification, make sure it complies with the
certification requirements.
The transactability and license management of these visuals are the responsibility of the
ISV. They can be managed using any platform, but we recommend Microsoft's Licensing
API. With the Licensing API, licensed visuals are purchased through AppSource and
customers can manage licenses in the M365 admin portal . For more information
about license management, see Frequently asked questions about Custom visual license
management.
) Important
If you update your Power BI visual from free to additional purchase may be required,
customers must receive the same level of free functionality as before the update.
You can add optional advanced paid features in addition to the existing free
features.
Watermarks
You can use watermarks to allow customers to continue using the IAP advanced features
without paying.
Watermarks let you showcase the full functionality of the Power BI visual to customers
before they make a purchase.
Only use watermarks on paid features used without a valid license. Watermarks aren't
allowed on free features of IAP visuals.
Pop-up window
Use a pop-up window to explain how to purchase a license when customers use an
invalid (or expired) license with your Power BI IAP visual.
Submission process
Follow the submission process, then navigate to the Offer setup tab. Select the My
product requires the purchase of a service check box.
After the Power BI visual is validated and approved, the Microsoft AppSource listing for
the IAP Power BI visual displays that more purchase may be required under the pricing
options.
Context menu
The context menu is the menu that displays when the user right-clicks inside a visual. All
Power BI visuals should enable the context menu to give users a unified experience. For
more information, see Add a context menu to your Power BI visual.
Commercial logo
This section describes the specifications for adding commercial logos in Power BI visuals.
Commercial logos aren't required. If you add them, make sure they follow these
guidelines.
7 Note
In this article, the term commercial logo refers to any commercial company
icon. See the following pictures.
The Microsoft commercial logo is used in this article only as an example. Use
your own commercial logo with your Power BI visual.
) Important
Commercial logos are allowed in edit mode only. Commercial logos can't be
displayed in view mode.
Logo
Symbol
Logotype
Tip
If your Power BI visual includes informative icons (i) in reading mode, they should
comply with the color, size, and location of the commercial logo, as described
earlier.
Avoid a colorful or a black commercial logo. The commercial logo must be grey
(hex color #C8C8C8).
Best practices
When publishing a Power BI visual, consider the following recommendations to give
customers the best possible experience.
Create a landing page that provides information about your Power BI visual.
Include details like how to use the visual and where to purchase the license. A
meaningful landing page helps report creators use the visual correctly and easily.
Don't include videos that are automatically triggered.
Add only material that improves the customer's experience, such as information or
links to license purchasing details and how to use IAP features.
For the customer's convenience, add the license key or token related fields at the
top of the format pane.
Submit a short screen-recording video that shows how to use the visual.
Submit a detailed description of the visual's functionality. Include information
about supported features such as high contrast, report page tooltip, and drill
down.
Check the quality of your code. Make sure it's up to standard, including unhandled
exceptions.
Update your visual using the latest API .
FAQ
For more information about Power BI visuals, see Frequently asked questions about
Power BI visuals with extra purchases.
Related content
Learn how you can publish your Power BI visual to for others to discover and use.
Feedback
Was this page helpful? Yes No
You can develop your own custom Power BI visuals tailored to your own or your
organization's specific needs. Usually, organizations develop their own custom visuals
when none of the visuals included with Power BI meet their exact needs.
Some organizations might have unique requirements for their Power BI visuals. They
might need visuals that can convey specific data or insights unique to their organization.
They might have special data requirements, or they might highlight private business
methods. These organizations can develop and maintain their own Power BI visuals that
they can share throughout their organization.
The Power BI administrator uses the Admin portal to deploy and manage organizational
visuals. After the visuals are deployed to the organizational repository, users in the
organization can easily discover and import them into their reports directly from Power
BI Desktop.
2 Warning
A Power BI visual installed from a file can contain code with security or privacy risks.
Make sure that you trust the author and the source of the Power BI visual file
before deploying it to the organization repository.
User considerations
Organizational Power BI visuals can't be exported to PowerPoint or displayed in
emails received when a user subscribes to report pages. Only certified Power BI
visuals imported directly from the marketplace support these features.
Certain visuals won't render if deployed through the organization's repository. Use
the Add from AppSource option in the Admin portal to manage the following
visuals:
Visio
Mapbox
Power Automate
Charticulator
Related content
Get a Power BI visual certified
Publish Power BI visuals to Partner Center
Frequently asked questions about Power BI visuals
Feedback
Was this page helpful? Yes No
When you buy a custom visual from AppSource , there are several business and
licensing models (pricing, free trials etc.) available. Some visuals have free trial versions,
while others have a basic version available for free with extra functionality available for
purchase.
7 Note
If you have an unlicensed visual in your report, the visual renders with an icon in
the corner. Hover over the icon for a link to that visual on AppSource.com.
If you have a free version of the visual, a banner appears with a link to upgrade
your license. This banner will disappear after a while.
If you try using a feature in the visual that you don't have a license to use, a banner
appears with a link to upgrade your license.
If you have an unlicensed visual in your report, the visual doesn't render, and a
button appears enabling you to get a license or contact the report owner.
Unsupported environment
If your report or dashboard contains a visual that isn't supported in your environment,
the visual doesn't render and a notification appears.
Solution
Select Upgrade visual to go to the AppSource page where you can buy the license or
upgrade to the paid version.
After you purchase and assign the license, it can take up to an hour for the license to be
recognized. Wait one hour and then refresh your Power BI session (restart Desktop or
refresh your web browser).
Related content
Import a Power BI visual
Feedback
Was this page helpful? Yes No
When you create Power BI visuals for download on AppSource, you can now manage
and enforce their licenses using Microsoft systems. The end-user assigns and manages
licenses using familiar tools like Microsoft 365 admin center , and the licensing API lets
you enforce these licenses and ensure that only licensed users can render the visuals.
Step Details
Create an offer in Choose to transact through the Microsoft commerce system. Enable
Partner Center Microsoft to manage licenses. Set pricing and availability.
Add license enforcement Create or reconfigure your package to use the Power BI runtime
to your Power BI visual license, which enforces licensing according to each user’s access.
package
Customers discover your When customers purchase your offer in AppSource , they also get
offer in AppSource and licenses for the Power BI Visual.
purchase a subscription
Customers manage their Customers manage subscriptions and assign licenses for these Visuals
subscriptions and and offers in the Microsoft 365 admin center , just like they do for
assign/unassign user any of their other subscriptions like Office or Power BI.
licenses
Enforce runtime checks Give your customers a uniform experience by using our out-of-the-
box APIs to enforce runtime license checks.
View reports to fuel Gain insight into revenue, payout information, and order and license
growth details. View information about licenses and orders purchased,
renewed, and canceled over time and by geography.
Licensing API
The Licensing API allows Power BI visual developers to enforce Power BI visual licenses.
The API supports retrieving the information on Power BI visual licenses that are assigned
to the Power BI user. It also enables triggering the licensing related notifications that will
appear on the Power BI visual and inform the user that they need to purchase the
missing licenses. The visual shouldn't display its own licensing UX, instead use one of
Power BI supported predefined notifications as detailed below.
7 Note
The Licensing API is available from version 4.7. To find out which version you’re
using, check the apiVersion in the pbiviz.json file.
once, preferably in the constructor or the init calls, and save the result.
Once licenses are retrieved, they'll be cached on Power BI host side during the Power BI
session and any further calls to the same will return the cached data.
TypeScript
TypeScript
plans - an array of Service Plans purchased by the active user for this visual.
(Licenses purchased for any other visuals aren't included in the response.)
A ServicePlan contains the service identifier (spIdentifier) and its state
(ServicePlanState).
spIdentifier: the string value of the Service ID generated when you configure
your offer’s plans in Partner Center (see the following example)
state – enum (ServicePlanState) that represents the state of the plans assigned.
Supported service plan states:
State Description
Inactive Indicates that the license isn't active and shouldn't be used for
provisioning benefits.
Active Indicates that the license is active and can be used for provisioning
benefits.
Warning Indicates that the license is in grace period likely due to payment violation.
Suspended Indicates that the license is suspended likely due to payment violation.
Only the active and warning states represent a usable license. All other states
should be treated as not resulting in a usable license.
Failure in licenses retrieval can occur in case Power BI Desktop user isn't signed in
or isn't connected to the internet (offline). For web, licenses retrieval can fail due to
a temporary service outage.
TypeScript
this.licenseManager.getAvailableServicePlans().then((result:
LicenseInfoResult) => {
this.notificationType = result.isLicenseUnsupportedEnv ?
powerbi.LicenseNotificationType.UnsupportedEnv :
powerbi.LicenseNotificationType.General;
this.hasServicePlans = !!(result.plans && result.plans.length &&
result.plans[0].spIdentifier ==
"test_isvconnect1599092224747.powerbivisualtransact.plan1" &&
( result.plans[0].state == powerbi.ServicePlanState.Active
|| result.plans[0].state == powerbi.ServicePlanState.Warning));
this.licenseManager.notifyLicenseRequired(this.notificationType).then((value
) => {
if (value) {
this.isIconDisplayed = true;
}
}).catch((err) => {
console.log('ERROR', err);
})
}
}).catch((err) => {
this.hasServicePlans = undefined;
console.log(err);
});
TypeScript
export interface IVisualLicenseManager {
notifyLicenseRequired(notificationType: LicenseNotificationType):
IPromise<boolean>;
notifyFeatureBlocked(tooltip: string): IPromise<boolean>;
clearLicenseNotification(): IPromise<boolean>;
}
7 Note
Example of the visual display containing the "licenses are required" general icon:
Example of the visual display containing the visual blocked notification. Power BI
Desktop will only display the Get a license option:
Overlay the visual's display with an unsupported
environment notification
Use notifyLicenseRequired call with LicenseNotificationType.UnsupportedEnv to overlay
the visual's display with a notification that visual is blocked since the Power BI in use
doesn't support licenses management\enforcement.
Once triggered, the icon will be preserved throughout the visual's lifetime until
clearLicenseNotification or notifyLicenseRequired are called.
7 Note
7 Note
The feature is blocked notification is only enforced when called in the context of
supported for licensing environment and in case blocking overlays aren't applied
( LicenseNotificationType.UnsupportedEnv ,
LicenseNotificationType.VisualIsBlocked ). Calling this notification in an
unsupported environment will not apply the notification and will return false in
the call's response.
7 Note
Once triggered, the banner will be displayed for 10 seconds, or until other "feature
blocked" banner is triggered, or until clearLicenseNotification is called (whatever
comes first).
Example of the visual display containing the "feature blocked" banner notification:
If you're creating a brand new offer, add the visual as a private plan for a test
customer account. The offer will only be visible to the this test account for
purchasing. Use this account to validate the offer before making it public.
If your visual is already available in AppSource and you want to upgrade it to a
licensed visual, you can't make it a private plan because that will hide the visual
from AppSource, and your existing users won't have access to it. There's currently
no way to test a published visual end to end. Test it the same way you tested the
original visual to AppSource, by mocking the licensing API value to check the
different possibilities.
Next steps
Publish a Power BI custom visual
This article answers some of the questions users often have about how to set up, pay
for, and manage licenses for custom Power BI visuals that they purchase from
AppSource .
7 Note
If you just purchased a licensed visual, you are assigned a license automatically.
Just refresh your report.
Purchasing
What are licensed visuals?
Licensed visuals are Power BI visuals available from the Microsoft commercial
marketplace . All licensed visuals have a limited basic version available for free, and a
version with more functionality available for purchase. You can try out a free version of
the visual before you need to purchase a license. You can also assign licenses to other
users in your organization.
Billing and Global admins can also pay by invoice if that's set up for your company.
Read more about setting payment methods. Follow these steps to see your billing
profile.
For troubleshooting payment and billing issues, see Troubleshoot Azure payment issues
and Troubleshoot a declined card.
License assignment
g
Who can assign licenses after the purchase is
complete?
The person who buys the visual is the owner, and only the owner can assign licenses.
7 Note
After buying the visual, the buyer (owner) is automatically assigned a license. Their
license is available after refreshing the report. It might take a few minutes.
If the tenant admin owns the licenses (organizational licenses), then any of the license
admins (Global Admin, License Admin or User Admin) can manage the licenses.
However, if the license owner isn't an admin, then only the purchaser/owner can
manage the subscription and licenses.
7 Note
After you assign a license in the Microsoft 365 Admin Center, the license should be
available within a few minutes.
If you were just assigned a license, refresh the report to activate it by doing one of the
following:
If you're using the licensed visual in the Power BI Service, refresh the report by
hitting F5 .
If you're using the licensed visual in the Power BI Desktop, close and reopen it.
If, after you refresh, the license is still not available, wait a while and try again. It could
take up to five minutes.
Can I sign in to Microsoft 365 admin center even
if I'm not an admin?
Yes. When you purchase a Power BI Visual subscription, you also get access to the
Microsoft 365 admin center. You can manage your own license subscriptions from there,
but can’t see or access any other subscriptions unless you're an admin.
Related content
Licensing models
Feedback
Was this page helpful? Yes No
This page contains a short summary of the existing API versions and what to expect in
the upcoming version. Versions listed here are considered stable and don't change.
API v5.10.0
DataViewMetadataColumn has a new property called sourceFieldParameters . This
property indicates if the current field is the result of a field parameter. If a single
field can originate from multiple field parameters, this property lists all the related
field parameters.
Supports Desktop June 2024
API v5.9.1
acquireAADTokenService: Enhanced to support the following clouds.
Commercial Cloud
China Cloud
US Government Community Cloud
US Government Community Cloud High
US Department of Defense Cloud
API v5.9.0
Hierarchial identity filter API: Allows you to create a visual that uses Matrix
DataView Mapping to filter data based on data points that use a hierarchal
structure. This is useful for custom visuals that leverage group-on keys semantic
models and want to filter hierarchies based on data points.
acquireAADTokenService: Extended with additional properties
Supports Desktop March 2024
API v5.8.0
Local storage API: A new version of local storage API available for all custom
visuals and controlled by a global admin setting that is on by default. The admin
can Turn off the global setting to disable both the legacy API and the new version
of the API.
On-object support for custom visuals: On object support for custom visuals to
optimize the user experience and provide a unified authoring experience on par
with out of the box visuals.
Supports Desktop February 2024
API v5.7.0
Power BI Custom Visuals Authentication API: Allows Custom Visuals to obtain
Microsoft Entra access tokens through single sign-on (SSO), facilitating secure and
efficient user-contextual operations.
Dynamic drill control: Allows the visual to enable or disable the drill feature
dynamically using an API call.
When the drill feature is enabled, all the functionalities of drilldown and
expand/collapse features are available. These functionalities include API calls,
context menu commands, header drill buttons, and support for hierarchy data.
When the drill feature is disabled, these functionalities aren't available.
Supports Desktop December 2023
API v5.4.0
Improved keyboard navigation: Improves accessibility and usability of your visuals
by providing more options for interacting with visual using the keyboard.
Detect filter use in reports: Detect if there are any filters applied to a report.
Supports Desktop May 2023
API v5.3.0
SelectionId's update-fix for matrix dataView .
7 Note
API v5.1.0
Custom sorting - improved custom sorting for tables
Subtotals - new Subtotals Type indicates if totals should be retrieved before or
after the rest of the data
Identity filter - filter categorical data
New format pane - design a custom visual that supports the new format pane
design
Supports Desktop October 2022
API v4.7.0
Licensing API - Sell, manage, and enforce licenses directly through the commercial
marketplace.
Drilldown API - Create a visual that can trigger a drilldown operation on its own,
without user interaction.
Supports Desktop July 2022
API v4.6.0
New capabilities property: privileges and two privileges:
web access
download file from custom visual
Added two corresponding tenant admin switches
Download API to allow downloading visual to file
Supports Desktop June 2022
API v4.2.0
New flags to expand and collapse row headers
Supports Desktop February 2022
API v3.8.0
Supports Desktop May 2021 and later.
API v3.7.0
Supports Desktop April 2021 and later.
API v3.6.0
Visual can receive updates from Power BI without the need to bind any data.
Supports Desktop 2021 February and later.
Supports Desktop RS May 2021 and later.
API v3.4.0
fetchMoreData : new aggregateSegments parameter (default true), for supporting
no-aggregation fetchMoreData
Supports Desktop 2020 November and later.
Supports Desktop RS January 2021 and later.
API v3.2.0
Supports supportsMultiVisualSelection
Supports Desktop 2019 September and later.
Supports Desktop RS January 2020 and later.
API v2.6.0
Adds isInFocus to update option and switchFocusModeState method to visual
host
Supports subtotals customization
Supports Desktop 2019 June and later.
Supports Desktop RS May 2019 and later.
API v2.5.0
Supports Analytics Pane
Supports SelectionIdBuilder withMatrixNode and withTable methods
No longer supports DataRepetitionSelector interface, replaced with
data.CustomVisualOpaqueIdentity interface
API v2.3.0
Landing Page API
Local Storage API
Tuple filter API (multi-column filter)
Rendering Events API
API v2.2.0
Supports restoring JSON Filter from DataView
ContextMenu API
Supports Drillthrough feature
API v2.1.0
Performance enhancements:
Faster load times
Smaller memory footprint
Optimized data and event transactions
Release notes
Refactored filtering APIs will be available in API 2.2 and are not supported in API
2.1.
Visuals will only receive the dataView type that was declared in their capabilities.
Visuals that used multiple dataView types will break as a result of this update.
undefined is replaced with null inside the dataView. When iterating over an array
using var item in myArray it skips on undefined , but doesn’t skip on null . Visuals
that use this pattern may be broken by this update. Make sure to check for null in
arrays:
TypeScript
The proto property no longer stores hidden metadata\data inside the dataView.
Visuals that access properties via proto may be broken by this update.
API v1.13.0
Supports Sync Slicers, note this only works for single field slicers due to PBI current
code state, read more.
Accessibility: High-contrast support
Accessibility: Allow Keyboard Focus flag
API v1.12.0
Supports Themes
Supports fetchMoreData, note the Fetch More Data API overcomes the hard limit
of 30K data points
Canvas Tooltips API
API v1.11.0
FilterManager API
Supports Bookmarks
API v1.10.0
Adds ILocalizationManager
Authentication API
API v1.9.0
launchUrl API
API v1.8.0
Supports new type fillRule (gradient) in capabilities schema
Supports rule property in capabilities schema for object properties
API v1.7.0
Supports RESJSON
API v1.6.2
Supports Edit mode for visual to enter in-visual edit mode
Supports Interactive (html) R Power BI visuals , based on html
API v1.5.0
Supports Allow interactions for visual interactivity
API v1.4.0
Supports Localization
API v1.3.0
Supports Tooltips
API v1.2.0
Adds colorPalette to manage the colors used on your visual.
Supports Multiple selection - selectionManager can accept an array of
SelectionId .
API v1.1.0
Supports debug visual in iFrame
Adds light weight sandbox with faster initialization of the iFrame
Fixes Capabilities.objects does not support "text" type issue
Supports pbiviz update to update visual API type definitions and schema
Supports --api-version flag in pbiviz new to create visuals with a specific api
version
Supports alpha release of API v1.2.0
Visual Host
Adds createSelectionIdBuilder to create unique identifiers used for data selection
Adds createSelectionManager to manage the selection state of the visual and
communicates changes to the visual host
Adds an array of default colors to use in visuals
API v1.0.0
Initial API release
Feedback
Was this page helpful? Yes No
A Power BI visual's landing page can display information in your Power BI visual card
before the card gets data. A visual's landing page can display:
This article explains how to design a landing page for your visual. The landing page
appears whenever the visual has no data in it.
7 Note
Designing a Power BI visual landing page is supported in API version 2.3.0 and
above. To find out which version you're using, check the apiVersion in the
pbiviz.json file.
JSON
{
"supportsLandingPage": true,
"supportsEmptyDataView": true,
}
TypeScript
constructor(options: VisualConstructorOptions) {
//...
this.element = options.element;
//...
}
} else {
if(this.isLandingPageOn && !this.LandingPageRemoved){
this.LandingPageRemoved = true;
this.LandingPage.remove();
}
}
}
Related content
Formatting utils
Feedback
Was this page helpful? Yes No
A launch URL lets you open a new browser tab or window by adding the
host.launchUrl() API call to the code of a Power BI visual.
7 Note
Sample
Import the IVisualHost interface and save the link to the host object in the constructor
of the visual.
TypeScript
// ...
}
Usage
Use the host.launchUrl() API call and pass your destination URL as a string argument:
TypeScript
this.host.launchUrl('https://some.link.net');
Best practices
Usually, it's best to open a link only as a response to a user's explicit action. Make
it easy for the user to understand that clicking the link or the button results in
opening a new tab. It can be confusing or frustrating for the user if a launchUrl()
call triggers without a user's action or as a side effect of a different action.
If the link isn't essential for the visual to function properly, we recommend that you
give the report's author a way to disable and hide the link. Special Power BI use
cases, such as embedding a report in a third-party application or publishing it to
the web, might require disabling and hiding the link.
Avoid triggering a launchUrl() call from inside a loop, the visual's update function,
or any other frequently recurring code.
A step-by-step example
TypeScript
this.helpLinkElement = this.createHelpLinkElement();
options.element.appendChild(this.helpLinkElement);
Add a private function that creates and attaches the anchor element:
TypeScript
Define the style for the link element with an entry in the visual.less file:
less
.helpLink {
position: absolute;
top: 0px;
right: 12px;
display: block;
width: 20px;
height: 20px;
border: 2px solid #80B0E0;
border-radius: 20px;
color: #80B0E0;
text-align: center;
font-size: 16px;
line-height: 20px;
background-color: #FFFFFF;
transition: all 900ms ease;
&:hover {
background-color: #DDEEFF;
color: #5080B0;
border-color: #5080B0;
transition: all 250ms ease;
}
&.hidden {
display: none;
}
}
Add the showHelpLink Boolean static object to the capabilities.json file's objects entry:
TypeScript
"objects": {
"generalView": {
"displayName": "General View",
"properties":
"showHelpLink": {
"displayName": "Show Help Button",
"type": {
"bool": true
}
}
}
}
}
TypeScript
if (settings.generalView.showHelpLink) {
this.helpLinkElement.classList.remove("hidden");
} else {
this.helpLinkElement.classList.add("hidden");
}
The hidden class is defined in the visual.less file to control the display of the element.
Currently, only HTTP and HTTPS protocols are supported. Avoid FTP, MAILTO, and
other protocols.
Feedback
Was this page helpful? Yes No
All visuals start with a class that implements the IVisual interface. You can name the
class anything as long as there's exactly one class that implements the IVisual
interface.
7 Note
The visual class name must be the same as the visualClassName in the pbiviz.json
file.
The visual class should implement the following methods as shown in the following
sample:
TypeScript
constructor(options: VisualConstructorOptions) {
//one time setup code goes here (called once)
}
TypeScript
constructor(options: VisualConstructorOptions)
VisualConstructorOptions
These interfaces get updated with each new API version. For the most updated interface
format, go to our GitHub repo .
element: HTMLElement - a reference to the DOM element that contains your visual
in your visual
createSelectionManager - creates the communication bridge used to notify the
visual's host about changes in the selection state, see Selection API.
hostCapabilities
refreshHostData
hostEnv
displayWarningIcon - returns error or warning message.
along with the visual definition, so they're available on the next reload
eventService - returns an event service to support Render events
storageService - returns a service to help use local storage in the visual
visual
tooltipService - returns a tooltip service to help use tooltips in the visual
telemetry
drill
fetchMoreData - supports using more data than the standard limit (1,000 rows).
update
All visuals must implement a public update method that's called whenever there's a
change in the data or host environment.
TypeScript
VisualUpdateOptions
viewport: IViewport - dimensions of the viewport that the visual should be
rendered within
dataViews: DataView[] - the data view object that contains all data needed to
render your visual (a visual generally uses the categorical property under
DataView)
type: VisualUpdateType - flags indicating the type of data being updated (Data |
InFocusEdit)
editMode: EditMode - flag indicating the edit mode of the visual (Default |
getFormattingModel (optional)
This method is called once each time we open the properties pane or the user edits any
of the properties in the pane. It returns FormattingModel with all information on the
properties pane design, hierarchy, properties, and latest formatting values.
TypeScript
getFormattingModel(): visuals.FormattingModel;
destroy (optional)
The destroy function is called when your visual is unloaded and can be used for clean-
up tasks such as removing event listeners.
TypeScript
Tip
Power BI generally doesn't call destroy since it's faster to remove the entire IFrame
that contains the visual.
Related content
Visual project structure
With the local storage API, you can store data in the browser's local storage. To use the
local storage API, the customer's local storage admin switch has to be enabled.
Local storage is isolated so that each type of visual has its own separate storage access.
7 Note
It’s developer’s responsibility to ensure that the stored data conforms to the
consumer’s organizational policies, and to inform users about what information is
stored, if the sensitivity of the data requires it. In particular, custom visual
developers should encrypt the data if business goals or scenarios expect it.
This version of the local storage API is scheduled for deprecation. We're not
accepting any more requests. When possible, use Version 2.
TypeScript
constructor(options: VisualConstructorOptions) {
// ...
this.storage = options.host.storageService;
// ...
this.storage.get(this.updateCountName).then(count =>
{
this.updateCount = +count;
})
.catch(() =>
{
this.updateCount = 0;
this.storage.set(this.updateCountName,
this.updateCount.toString());
});
// ...
}
The local storage API doesn't support await constructions. Only then and
catch methods are allowed.
Related content
Power BI custom visual API
Authentication API
Article • 06/26/2024
The Authentication API enables visuals to obtain Microsoft Entra ID (formerly known as
Azure AD) access tokens for signed-in users, facilitating single sign-on authentication.
Power BI administrators can enable or disable the API through a global switch. The
default setting blocks (disables) the API.
The API is applicable only for AppSource visuals, and not for private visuals. Visuals that
are under development can be tested in debug mode before they're published.
Supported environments
The following environments are supported:
Web
Desktop
RS Desktop
Mobile
Unsupported environments
The following environments aren't yet supported:
RS Service
Embedded analytics
Teams
JSON
"privileges": [
{
"name": "AADAuthentication",
"parameters": {
"COM": "https://contoso.com",
"CN": "https://contoso.cn"
}
}
]
TypeScript
/**
* Enum representing the various clouds supported by the Authentication
API.
*/
export const enum CloudName {
COM = "COM", // Commercial Cloud
CN = "CN", // China Cloud
GCC = "GCC", // US Government Community Cloud
GCCHIGH = "GCCHIGH", // US Government Community Cloud High
DOD = "DOD", // US Department of Defense Cloud
}
/**
* Interface representing information about the user associated with
the token.
*/
export interface AcquireAADTokenUserInfo {
userId?: string; // Unique identifier for the user
tenantId?: string; // Unique identifier for the tenant
}
/**
* Interface representing information about the fabric environment.
*/
export interface AcquireAADTokenFabricInfo {
cloudName?: CloudName; // Name of the cloud environment
}
/**
* Interface representing the result of acquiring a Microsoft Entra ID
token.
*/
export interface AcquireAADTokenResult {
accessToken?: string; // Access token issued by Microsoft
Entra ID
expiresOn?: number; // Expiration time of the access token
userInfo?: AcquireAADTokenUserInfo; // Information about the
user associated with the token
fabricInfo?: AcquireAADTokenFabricInfo; // Information about the
fabric environment
}
The following sample code demonstrates how to acquire a Microsoft Entra ID token
using the API:
TypeScript
The visual’s backend service, configured as the audience by the visual, doesn't have
appropriate consents for the Graph API in the consumer tenant using the visual.
For more about consent, see tenant administrator consent.
Related content
Microsoft Entra ID application setup
Feedback
Was this page helpful? Yes No
On-object formatting allows users to quickly and easily modify the format of visuals by
directly selecting the elements they want to modify. When an element is selected, the
format pane automatically navigates and expands the specific formatting setting for the
selected element. For more information about on-object formatting, see On-object
formatting in Power BI Desktop.
To add these functionalities to your visual, each visual needs to provide a subselection
style option and shortcut for each subselectable region.
7 Note
Format mode
Format mode is a new mode where the user can turn onObject formatting on and off
when in authoring mode. The visual is updated with the status of the format mode in
the update options. The update options also include the currently subselected
subSelection as CustomVisualSubSelection .
Capabilities file
In the capabilites.json file, add the following properties to declare that the visual
supports on-object formatting:
JSON
{
"supportsOnObjectFormatting": true,
"enablePointerEventsFormatMode": true,
}
IVisual interface
The visual needs to implement the VisualOnObjectFormatting interface as part of the
IVisual interface.
getSubSelectionStyles
getSubSelectionShortcuts
getSubSelectables
getSubSelectionStyles
Each visual is required to implement a getSubSelectionStyles method, which is called
when a subselectable element is subselected. The getSubSelectionStyles method is
provided with the current subselected elements as a CustomVisualSubSelection array
and is expected to return either a SubSelectionStyles object or undefined .
There are three categories of subselection styles that cover most scenarios:
Text
Numeric Text
Shape
Each SubSelectionStyles object provides a different experience for the user for
modifying the style of an element.
getSubSelectionShortcuts
To provide more options for the user, the visual must implement the
getSubSelectionShortcuts method. This method returns either
VisualSubSelectionShortcuts or undefined . Additionally, if SubSelectionShortcuts are
provided, a VisualNavigateSubSelectionShortcut must also be provided so that when a
user subselects an element and the format pane is open, the pane automatically scrolls
to the appropriate card.
There are several subselection shortcuts to modify the visual state. Each one defines a
menu item in the context menu with the appropriate label.
getSubSelectables
To provide subselections to the disambiguation menu, the visual needs to implement
the getSubSelectables method. This method is provided an optional filterType
argument, of type SubSelectionStylesType and returns an array of
CustomVisualSubSelection or undefined . If the HTMLSubSelectionHelper is being utilized
Sub-Selection Direct Text Editing: With On-Object formatting, you can double-click the
text of a subs-electable element to directly edit it. To provide direct-edit capability, you
need to provide a RectangleSubSelectionOutline with the appropriate cVDirectEdit
Property populated with a SubSelectableDirectEdit object. The outline can either be
provided as a custom outline or, if you're using the HTMLSubSelectionHelper you can use
the SubSelectableDirectEdit attribute. (See the attributes provided by the
HTMLSubSelectionHelper)
Adding a direct edit for a specific datapoint (using selectors) isn't yet supported.
FormattingId interface
The following interface is used to reference the subSelection shortcuts and styles.
TypeScript
interface FormattingId {
objectName: string;
propertyName: string;
selector?: powerbi.data.Selector;
}
Examples
In this example, we build a custom visual that has two objects, colorSelector and
directEdit . We use the HTMLSubSelectionHelper from the onobjectFormatting utils, to
handle most of the subSelection job. For more information, see on-object utils.
First, we build cards for the formatting pane and provide subSelectionShortcuts and
styles for each subselectable.
JSON
"objects": {
"directEdit": {
"properties": {
"show": {
"displayName": "Show",
"type": {
"bool": true
}
},
"textProperty": {
"displayName": "Text",
"type": {
"text": true
}
},
"fontFamily": {
"type": {
"formatting": {
"fontFamily": true
}
}
},
"fontSize": {
"type": {
"formatting": {
"fontSize": true
}
}
},
"bold": {
"type": {
"bool": true
}
},
"italic": {
"type": {
"bool": true
}
},
"underline": {
"type": {
"bool": true
}
},
"fontColor": {
"displayName": "Font Color",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"background": {
"displayName": "Background",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"position": {
"displayName": "Position",
"type": {
"enumeration": [
{ "displayName": "Left", "value": "Left" }, { "displayName":
"Right", "value": "Right" }
]
}
}
}
},
"colorSelector": {
"displayName": "Data Colors",
"properties": {
"fill": {
"displayName": "Color",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
},
},
"supportsOnObjectFormatting": true,
"enablePointerEventsFormatMode": true,
TypeScript
Add a method to the formattingSetting so we can populate the slices dynamically for
the colorSelector object (our datapoints).
TypeScript
populateColorSelector(dataPoints: BarChartDataPoint[]) {
let slices: formattingSettings.ColorPicker[] =
this.colorSelector.slices;
if (dataPoints) {
dataPoints.forEach(dataPoint => {
slices.push(new formattingSettings.ColorPicker({
name: "fill",
displayName: dataPoint.category,
value: { value: dataPoint.color },
selector: dataPoint.selectionId.getSelector(),
}));
});
}
}
We pass the selector of the specific datapoint in the selector field. This selector is the
one used when implementing the get APIs of the OnObject.
TypeScript
TypeScript
import {
HtmlSubSelectableClass, HtmlSubSelectionHelper,
SubSelectableDirectEdit as SubSelectableDirectEditAttr,
SubSelectableDisplayNameAttribute, SubSelectableObjectNameAttribute,
SubSelectableTypeAttribute
} from 'powerbi-visuals-utils-onobjectutils';
this.directEditElement
.classed('direct-edit', true)
.classed('hidden',
!this.formattingSettings.directEditSettings.show.value)
.classed(HtmlSubSelectableClass, options.formatMode &&
this.formattingSettings.directEditSettings.show.value)
.attr(SubSelectableObjectNameAttribute, 'directEdit')
.attr(SubSelectableDisplayNameAttribute, 'Direct Edit')
.attr(SubSelectableDirectEditAttr,
this.visualDirectEditSubSelection)
TypeScript
barSelectionMerged
.attr(SubSelectableObjectNameAttribute, 'colorSelector')
.attr(SubSelectableDisplayNameAttribute, (dataPoint:
BarChartDataPoint) =>
this.formattingSettings.colorSelector.slices[dataPoint.index].displayNa
me)
.attr(SubSelectableTypeAttribute,
powerbi.visuals.SubSelectionStylesType.Shape)
.classed(HtmlSubSelectableClass, options.formatMode)
Define references
Define the following interface to simplify the examples:
7 Note
The cardUid you provide should be the same as the one provided for the
getFormattingModel API. For example, if you're using powerbi-visuals-utils-
formattingmodel, provide the cardUid as Visual-cardName-card, where the
cardName is the name you assigned to this card in the formatting model settings.
Otherwise, provide it as the Visual-cardUid you assigned to this card.
TypeScript
interface References {
cardUid?: string;
groupUid?: string;
fill?: FormattingId;
font?: FormattingId;
fontColor?: FormattingId;
show?: FormattingId;
fontFamily?: FormattingId;
bold?: FormattingId;
italic?: FormattingId;
underline?: FormattingId;
fontSize?: FormattingId;
position?: FormattingId;
textProperty?: FormattingId;
}
For the purpose of this example, create an enum for the objects names:
TypeScript
TypeScript
For colorSelector :
TypeScript
Implement APIs
Now let's implement the get APIs for the onObject formatting and provide them in the
visualOnObjectFormatting:
public visualOnObjectFormatting:
powerbi.extensibility.visual.VisualOnObjectFormatting;
constructor(options: VisualConstructorOptions) {
this.subSelectionHelper =
HtmlSubSelectionHelper.createHtmlSubselectionHelper({
hostElement: options.element,
subSelectionService: options.host.subSelectionService,
selectionIdCallback: (e) =>
this.selectionIdCallback(e),
});
this.visualOnObjectFormatting = {
getSubSelectionStyles: (subSelections) =>
this.getSubSelectionStyles(subSelections),
getSubSelectionShortcuts: (subSelections, filter) =>
this.getSubSelectionShortcuts(subSelections, filter),
getSubSelectables: (filter) => this.
getSubSelectables(filter)
}
}
private getSubSelectionStyles(subSelections:
CustomVisualSubSelection[]): powerbi.visuals.SubSelectionStyles |
undefined {
const visualObject = subSelections[0]?.customVisualObjects[0];
if (visualObject) {
switch (visualObject.objectName) {
case BarChartObjectNames.ColorSelector:
return this.getColorSelectorStyles(subSelections);
case BarChartObjectNames.DirectEdit:
return this.getDirectEditStyles();
}
}
}
private getSubSelectionShortcuts(subSelections:
CustomVisualSubSelection[], filter: SubSelectionShortcutsKey |
undefined): VisualSubSelectionShortcuts | undefined {
const visualObject = subSelections[0]?.
customVisualObjects[0];
if (visualObject) {
switch (visualObject.objectName) {
case BarChartObjectNames.ColorSelector:
return
this.getColorSelectorShortcuts(subSelections);
case BarChartObjectNames.DirectEdit:
return this.getDirectEditShortcuts();
}
}
}
2. Implement the getSubSelection shortcuts and style for the colorSelector:
TypeScript
private getColorSelectorShortcuts(subSelections:
CustomVisualSubSelection[]): VisualSubSelectionShortcuts {
const selector =
subSelections[0].customVisualObjects[0].selectionId?.getSelector();
return [
{
type: VisualShortcutType.Reset,
relatedResetFormattingIds: [{
...colorSelectorReferences.fill,
selector
}],
},
{
type: VisualShortcutType.Navigate,
destinationInfo: { cardUid:
colorSelectorReferences.cardUid },
label: 'Color'
}
];
}
The above shortcut returns relevant menu item in the context menu and adds the
following functionalities:
TypeScript
private getColorSelectorStyles(subSelections:
CustomVisualSubSelection[]): SubSelectionStyles {
const selector =
subSelections[0].customVisualObjects[0].selectionId?.getSelector();
return {
type: SubSelectionStylesType.Shape,
fill: {
label: 'Fill',
reference: {
...colorSelectorReferences.fill,
selector
},
},
};
}
Subsection shortcuts
To implement the subSelection shortcuts and styles for the directEdit:
TypeScript
This shortcut adds a relevant menu item in the context menu and adds the following
functionalities:
TypeScript
The following image illustrates how the UI looks when right-clicking on the directEdit
element:
Localization
The visual should handle the localization and provide localized strings.
GitHub resources
All on object formatting interfaces can be found in (link to be provided once the
API is released) in on-object-formatting-api.d.ts
We recommend using the [on object utils], which include the
[HTMLSubSelectionHelper](link to be provided once the API is released)
You can find an example of a custom visual SampleBarChart that uses API version
5.8.0 and implements the support for the on object formatting using the on object
utils at (link to be provided once the API is released)
Related content
Subselection API
On-object utils
Subselection API (preview)
Article • 02/19/2024
On-object formatting allows users to quickly and easily modify the format of visuals by
directly selecting the elements they want to modify. When an element is selected, the
format pane automatically navigates and expands the specific formatting setting for the
selected element. As part of on-object formatting, the subselection service is used to
send subselections and outlines to Power BI.
subSelect
updateRegionOutlines
subSelect
Sends the subselection for Power BI to use when a user selects an element that allows
subselections.
TypeScript
CustomVisualSubSelection
interface CustomVisualSubSelection {
customVisualObjects: CustomVisualObject[];
displayName: string;
subSelectionType: SubSelectionStylesType;
selectionOrigin: SubSelectionOrigin;
/** Whether to show the UI for this sub-selection, like
formatting context menus and toolbar */
showUI: boolean;
/** If immediate direct edit should be triggered, the ID of the
sub-selection outline to edit */
immediateDirectEdit?: string;
metadata?: unknown;
}
interface CustomVisualObject {
objectName: string;
selectionId: powerbi.visuals.ISelectionId | undefined;
}
This method has the following parameters:
If you don't use the HTMLSubSelectionHelper, you need to manage the subselections.
Subselection example
In this example, we add an event listener to the host element, for the right-click, context
menu events.
TypeScript
constructor(options: VisualConstructorOptions) {
this.hostElement = options.element;
this.subSelectionService = options.host.subSelectionService;
….
}
updateRegionOutlines
This method sends outlines to Power BI to render. Use it in the update method of the
visual since that's where Power BI sends the subselection that the visual sent previously.
You can also use it when you want to render an outline for a hovered element.
tyepscript
SubSelectionRegionOutline
interface SubSelectionRegionOutline {
id: string;
visibility: SubSelectionOutlineVisibility; // controls
visibility for outlines
outline: SubSelectionOutline;
}
If you don't use the HTMLSubSelectionHelper, you have to manually manage the
outlines and their state (if they're active, hovered or not visible).
Update region outlines example
In this example we assume that we have an object called myObject , and we want to
render a rectangle outline when the relevant element is hovered. We use the code in the
previous example for subSelect.
In the update, we also need to add an event listener for the pointerover event.
TypeScript
Related content
On object utils
On-object formatting API
The Visual Filters API in Power BI visuals
Article • 06/06/2024
The Visual Filters API allows you to filter data in Power BI visuals. The main difference
between the filter API and other ways of selecting data is how it affects other visuals in
the report. When a filter is applied to a visual, only the filtered data will be visible in all
visuals, despite highlight support by other visuals.
To enable filtering for the visual, the capabilities.json file should contain a filter object
in the general section.
JSON
"objects": {
"general": {
"displayName": "General",
"displayNameKey": "formattingGeneral",
"properties": {
"filter": {
"type": {
"filter": true
}
}
}
}
}
7 Note
If you're using an older (earlier than 3.x.x) version of the tools, include
powerbi-models in the visuals package. For more information, see the short
guide, Add the Advanced Filter API to the custom visual . To find out which
version you’re using, check the apiVersion in the pbiviz.json file.
All filters use the IFilter interface, as shown in the following code:
TypeScript
TypeScript
Where:
TypeScript
let basicFilter = {
target: {
column: "Col1"
},
operator: "In",
values: [1,2,3]
}
The SQL equivalent of the above example is:
SQL
If you are using an older version of the tool, you should get an instance of models in the
window object by using window['powerbi-models'] , as shown in the following code:
JavaScript
let values = [ 1, 2, 3 ];
The visual invokes the filter by calling the applyJsonFilter() method on the host
interface, IVisualHost , which is provided to the visual in the constructor method.
TypeScript
TypeScript
interface IAdvancedFilterCondition {
value: (string | number | boolean);
operator: AdvancedFilterConditionOperators;
}
Condition operators for the operator parameter are: None, LessThan, LessThanOrEqual,
GreaterThan, GreaterThanOrEqual, Contains, DoesNotContain, StartsWith,
DoesNotStartWith, Is, IsNot, IsBlank, and "IsNotBlank"`
JavaScript
conditions.push({
operator: "LessThan",
value: 0
});
SQL
TypeScript
Where
TypeScript
$schema is https://powerbi.com/product/schema#tuple .
filterType is FilterType.Tuple.
TypeScript
interface ITupleElementValue {
value: PrimitiveValueType
}
Complete example:
TypeScript
let values = [
[
// the first column combination value (or the column tuple/vector
value) that the filter will pass through
{
value: "Team1" // the value for the `Team` column of the
`DataTable` table
},
{
value: 5 // the value for the `Value` column of the `DataTable`
table
}
],
[
// the second column combination value (or the column tuple/vector
value) that the filter will pass through
{
value: "Team2" // the value for `Team` column of `DataTable`
table
},
{
value: 6 // the value for `Value` column of `DataTable` table
}
]
];
) Important
SQL
TypeScript
When you switch bookmarks, Power BI calls the update method of the visual, and the
visual gets a corresponding filter object. For more information, see Add bookmark
support for Power BI visuals.
TypeScript
Related content
Use Power BI visuals selections to add interactivity to a visual
Feedback
Was this page helpful? Yes No
The Identity filter API allows you to create a visual that can filter categorical data using
a semantic query.
It filters the data by data points rather than mathematical expressions.
The API keeps track of user selections and which data points to display. The data points
are saved in an array and referenced by their position in the array.
For custom visuals that use semantic models with group on keys
Migrating visuals that used an older API (earlier than 2.2) to a newer API
Allow selections using identifying index arrays
7 Note
The Identity filter API is available from API version 5.1 To find out which version
you’re using, check the apiVersion in the pbiviz.json file.
TypeScript
For example, if the visual received the following data view update:
The array is of type number[] and it contains the identity fields of the items that the user
selected.
The identityIndex corresponds to the index of the value in the semantic model's value
array (see the following example).
TypeScript
To handle user selections in the previous example, click on the first Abigail to add
the value 8 to the filter target array and send it using the following command:
TypeScript
JSON
"migration": {
"filter": {
"shouldUseIdentityFilter": true
}
}
7 Note
This step is only necessary for existing visuals created with older APIs. Newer visuals
don't need to add this.
Related content
Use Power BI visuals selections to add interactivity to a visual
Feedback
Was this page helpful? Yes No
The Hierarchy Identity filter API enables visuals that use Matrix DataView Mapping to
filter data on multiple fields at a time based on data points that use a hierarchy
structure.
7 Note
The Hierarchy Identity filter API is available from API version 5.9.0
TypeScript
target: Array of relevant columns in the query. Currently only a single role is
supported; therefore, the target isn't required and should be empty.
hierarchyData: the selected and unselected items in a hierarchy tree where each
IHierarchyIdentityFilterNode<IdentityType> represents a single value selection.
TypeScript
interface IQueryNameTarget {
queryName: string;
}
queryName: query name of the source column in the query. It comes from the
DataViewMetadataColumn
TypeScript
interface IHierarchyIdentityFilterNode<IdentityType> {
identity: IdentityType;
children?: IHierarchyIdentityFilterNode<IdentityType>[];
operator: HierarchyFilterNodeOperators;
}
operator: The operator for single objects in the tree. The operator can be one of
the following three options:
TypeScript
Keep the following rules in mind when defining your hierarchy identity filter:
The identities might change following fields changes (for example, adding or
removing fields). Power BI assigns the updated identities to the existing
filter.hierarchyData.
How to use the Hierarchy identity filter API
The following code is an example of how to use the hierarchy identity filter API in a
custom visual:
TypeScript
const hierarchyData:
IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity>[] = [
{
identity: {...},
operator: "Selected",
children: [
{
identity: {...},
operator: "NotSelected"
}
]
},
{
identity: {...},
operator: "Inherited",
children: [
{
identity: {...},
operator: "Selected"
}
]
}
];
TypeScript
To restore the active JSON filter, use the jsonFilters property found in the
"VisualUpdateOptions":
TypeScript
export interface VisualUpdateOptions extends
extensibility.VisualUpdateOptions {
//...
jsonFilters?: IFilter[];
}
TypeScript
"dataViewMappings": [
{
"conditions": [
{
"Rows": {
"min": 1,
"areHierarchicallyRelated": true <------ NEW ------>
},
"Value": {
"min": 0
}
}
],
...
}
]
The relationship direction matches the cardinality for one to many or bidirectional.
7 Note
When these validations are enabled, and the fields are not hierarchically
related, the visual won't render, and an error message will be displayed:
When these validations are disabled, and the filter visual applies a filter that
contains nodes related to non-hierarchically related fields, other visuals might
not render properly when measures are in use:
Code example for updating the hierarchy data
tree after new selection
The following code shows how to update the hierarchyData tree after new a selection:
TypeScript
A visual that uses the Hierarchy identity filter type should apply only a single filter
of this type.
Feedback
Was this page helpful? Yes No
7 Note
TypeScript
Related content
Use Power BI visuals selections to add interactivity to a visual
Feedback
Was this page helpful? Yes No
In order to get a visual certified, it must include rendering events. These events let
listeners (primarily, export to PDF and export to PowerPoint) know when the visual is
being rendered and when it's ready for export.
) Important
Any visual that exports data (for example, to a PowerPoint or .pdf file) must contain
rendering events to ensure that the export doesn't begin before the visual finished
rendering.
The rendering events API consists of three methods that should be called during
rendering:
indicate that the rendering process started. This method should always be the
first line of the update method since that is where the rendering process begins.
code calls the renderingFinished method to notify the listeners that the visual's
image is ready for export. This method should be the last line of code executed
when the visual updates. It's usually, but not always, the last line of the update
method.
visual doesn't render successfully. To notify the listeners that the rendering process
wasn't completed, the Power BI visual code should call the renderingFailed
method. This method also provides an optional string to provide a reason for the
failure.
7 Note
Rendering events are a requirement for visuals certification. Without them your
visual won't be approved by the Partner Center for publication. For more
information, see certification requirements.
TypeScript
TypeScript
TypeScript
this.events = options.host.eventService;
TypeScript
constructor(options: VisualConstructorOptions) {
...
this.events = options.host.eventService;
...
}
function, even if it's not the last line of the update method.
TypeScript
constructor(options: VisualConstructorOptions) {
...
this.events = options.host.eventService;
this.element = options.element;
...
}
d3.select(this.element).transition().duration(100).style("opacity","0").end(
).then(() => {
// renderingFinished called after transition end
this.events.renderingFinished(options);
});
}
Related content
Visual API
Feedback
Was this page helpful? Yes No
The Drilldown API allows you to create a visual that can trigger a drilldown operation on
its own, without user interaction.
The API enables the visual to show next level, expand to next level, or drill up based on
the parameters passed to the API. For more information about drilling down, see Drill
down support.
7 Note
The Drilldown API is available from API version 4.7.0 To find out which version
you’re using, check the apiVersion in the pbiviz.json file.
JSON
"drilldown": {
"roles": ["Rows", "Columns"]
}
TypeScript
7 Note
The dynamic drill control feature allows the visual to enable or disable the drill feature
dynamically using an API call. When the drill feature is enabled, all drilldown
functionalities and expand/collapse features are available, including API calls, context
menu commands, header drill buttons, and support for hierarchy data. When disabled,
these functionalities aren't available.
The following images show an example of a visual with the dynamic drill control feature
enabled and disabled:
Drill enabled
The dynamic drill control feature includes the following API elements:
TypeScript
export interface DataRolesInfo {
//…
isDrillDisabled?: boolean; // ----- NEW -----
}
TypeScript
To identify whether the drill is disabled, use the isDrillDisabled property in the update
method:
TypeScript
Then use the API call to enable or disable the drill as needed:
A visual with the dynamic drill control feature, has the following code in the
capabilities.json file:
JSON
"drilldown": {
"roles": [
"Rows",
"Columns"
],
"canDisableDrill": {
"disabledByDefault": true
}
},
JSON
"drilldown": {
"roles": [
"Rows",
"Columns"
],
"canDisableDrill": {}
},
The canDisableDrill property indicates that the visual supports this feature. Without
this property, the API call isn't respected.
The disabledByDefault property indicates whether or not to disable the drill feature by
default.
7 Note
The disabledByDefault property takes effect when you do one of the following
actions:
this feature. If sourceVisual does support this feature, the targetVisual keeps the
sourceVisual's state and not the default.
If, however, you want to keep the same GUID, keep in mind the following points:
When you migrate from a nondrillable version to a new drillable version, some
data might not be provided in the dataView due to the hierarchical data support
introduced as part of the drill feature. The dynamic drill control feature doesn't
offer automatic support for this issue but can be used to manage the migration
process.
For self-migration of the visual, the visual should take the following actions:
Identify the first time the new version is loaded instead of the older version, and
apply the persistProperties API.
Disable the drill to receive all the data, using the setCanDrill API.
The following example shows how to self-migrate an older visual to one that uses
dynamic drill control:
JSON
"DrillMigration": {
"displayName": "Drill Migration",
"properties": {
"isMigrated": {
"displayName": "Is Drill Migrated",
"type": {
"bool": true
}
}
}
},
TypeScript
this.host.setCanDrill(!this.drillMigration.disabledByDefault);
this.isCalledToDisableDrillInMigrationScenario = true;
}
}
}
}
}
private persistMigrationProperty(): void {
let property = {
merge: [{
objectName: "DrillMigration",
properties: {
isMigrated: true
},
selector: null
}]
};
this.host.persistProperties(property);
}
}
The first time the visual is opened after adding this code, the DrillMigration variable is
set to true and the visual opens in the default state.
Considerations and limitations
The drill state isn't saved after disabling the drill. If you reenable the drill after
disabling it, only the first level is displayed regardless of what was displayed before
it was disabled.
The expand/collapse state isn't saved after disabling the drill. All the rows are
collapsed once the drill is reenabled.
Data view mapping conditions: Use "max": 1 for all conditions for the drillable role
to limit the visual to showing only one field when drill is disabled. For example:
JSON
"conditions": [
{ "category": { "min": 1 }, "measure": { "max": 1 }}
]
JSON
"conditions": [
{ "Rows": { "max": 0 }, "Columns": { "max": 0 }, "Value": {
"min": 1 } },
{ "Rows": { "min": 1 }, "Columns": { "min": 0 }, "Value": {
"min": 0 } },
{ "Rows": { "min": 0 }, "Columns": { "min": 1 }, "Value": {
"min": 0 } },
]
Feedback
Was this page helpful? Yes No
The file download API lets users download data from a custom visual into a file on their
storage device. Downloading a visual requires user consent and admin permission
provided in the admin global switch. This setting is separate from and not affected by
download restrictions applied in your organization's export and sharing tenant settings.
7 Note
Use the file download API to export to files of the following types:
.txt
.csv
.json
.tmplt
.xml
.pdf
.xlsx
Before the download begins, a window appears asking to confirm that the visual is from
a trusted source.
content: string
filename: string
fileType: string - When exporting to a .pdf or .xlsx file, the fileType parameter
should be base64
fileDescription: string
This method returns a promise that will be resolved for a Boolean value.
content: string
filename: string
fileType: string - When exporting to a .pdf or .xlsx file, the fileType parameter
should be base64
fileDescription: string
This method returns a promise, which will be resolved with a result of type
ExportContentResultInfo that contains the following parameters:
TypeScript
constructor(options: VisualConstructorOptions) {
this.downloadService = options.host.downloadService;
...
this.downloadService.exportVisualsContent(contentXlsx,
"myfile.xlsx", "base64", "xlsx file").then((result) => {
if (result) {
//do something
}
}).catch(() => {
//handle error
});
this.downloadService.exportVisualsContentExtended(contentXlsx,
"myfile.xlsx", "base64", "xlsx file").then((result) => {
if (result.downloadCompleted) {
//do something
console.log(result.fileName);
}
}).catch(() => {
//handle error
});
};
} catch (err) {
//handle error
}
}
}
}
Considerations and limitations
The API is supported only in the Power BI service and Power BI desktop
The size limit for a downloaded file is 30 MB.
This API is a privileged API.
Related content
Learn about the Visual API
Feedback
Was this page helpful? Yes No
As a developer of Power BI visuals, you can develop visuals that need permission to
access various resources. You request these permissions in the privileges section of the
capabilities.json file. These privileges include the ability to access:
Each organization's admin can allow or block these permissions. The check permissions
API allows you to query the host at runtime to determine which permissions are
granted. You can use this information to design a visual that will work with various
permission settings.
The check permissions API returns the status of each permission query function:
TypeScript
/**
* Represents a return type for privilege status query methods
*/
export const enum PrivilegeStatus {
/**
* The privilege is allowed in the current environment
*/
Allowed,
/**
* The privilege declaration is missing in visual capabilities section
*/
NotDeclared,
/**
* The privilege is not supported in the current environment
*/
NotSupported,
/**
* The privilege usage was denied by tenant administrator
*/
DisabledByAdmin,
}
Allowed
Not declared
Not supported
Disabled by Admin
Web access
TypeScript
Export content
TypeScript
Related content
Power BI custom visual API
How to add external libraries
Article • 01/09/2024
This article describes how to use external libraries in Power BI visuals. This article also
describes how to install, import, and call external libraries from a Power BI visual's code.
JavaScript libraries
1. Install an external JavaScript library by using a package manager, such as npm or
yarn.
2. Import the required modules into the source files using the external library.
7 Note
To add typings to your JavaScript library, and get Intellisense and compile-time
safety, make sure that you install the appropriate package.
PowerShell
2. Import the d3 library in the files that use it, such as visual.ts.
TypeScript
CSS framework
1. Install an external CSS framework by using any package manager, such as npm or
yarn.
2. In the .less file of the visual, include the import statement.
Installing bootstrap
This section provides an example of installing bootstrap using npm .
PowerShell
less
Related content
Set up your environment for developing a Power BI visual
Feedback
Was this page helpful? Yes No
Interactivity utils ( InteractivityUtils ) is a set of functions and classes that can be used
to simplify the implementation of cross-selection and cross-filtering.
7 Note
The latest updates of interactivity utils support only the latest version of tools (3.x.x
and above).
Installation
1. To install the package, run the following command in the directory with your
current Power BI visual project.
Bash
2. If you're using version 3.0 or later of the tool, install powerbi-models to resolve
dependencies.
Bash
3. To use interactivity utils, import the required component in the source code of the
Power BI visual.
TypeScript
Import the CSS file as a .less file because the Power BI visuals tool wraps external CSS
rules.
less
SelectableDataPoint properties
Usually, data points contain selections and values. The interface extends the
SelectableDataPoint interface.
TypeScript
/** Identity for identifying the selectable data point for selection
purposes */
identity: powerbi.extensibility.ISelectionId;
/*
* A specific identity for when data points exist at a finer granularity
than
* selection is performed. For example, if your data points select based
* only on series, even if they exist as category/series intersections.
*/
specificIdentity?: powerbi.extensibility.ISelectionId;
TypeScript
TypeScript
7 Note
TypeScript
import {
IBehaviorOptions,
BaseDataPoint
} from "./interactivityBaseService";
When a user clicks data elements, the visual calls the selection handler to select
data points. If the user clicks the background element of the visual, it calls the clear
selection handler.
bindClick
bindClearCatcher
bindContextMenu .
TypeScript
protected bindClick() {
// ...
}
protected bindClearCatcher() {
// ...
}
protected bindContextMenu() {
// ...
}
public bindEvents(
options: BaseBehaviorOptions<SelectableDataPointType>,
selectionHandler: ISelectionHandler): void {
// ...
}
5. To handle a click on elements, call the d3 selection object on method. This also
applies for elementsSelection and clearCatcherSelection .
TypeScript
protected bindClick() {
const {
elementsSelection
} = this.options;
6. Add a similar handler for the contextmenu event, to call the selection manager's
showContextMenu method.
TypeScript
protected bindContextMenu() {
const {
elementsSelection
} = this.options;
7. To assign functions to handlers, the interactivity utils calls the bindEvents method.
Add the following calls to the bindEvents method:
bindClick
bindClearCatcher
bindContextMenu
TypeScript
public bindEvents(
options: BaseBehaviorOptions<SelectableDataPointType>,
selectionHandler: ISelectionHandler): void {
this.options = options;
this.selectionHandler = selectionHandler;
this.bindClick();
this.bindClearCatcher();
this.bindContextMenu();
}
TypeScript
TypeScript
this.interactivity.bind(<BaseBehaviorOptions<VisualDataPoint>>{
behavior: this.behavior,
dataPoints: this.categories,
clearCatcherSelection: select(this.target),
elementsSelection: selectionMerge
});
selectable elements.
TypeScript
Related content
Visuals with selection
Feedback
Was this page helpful? Yes No
Formatting utils contain classes, interfaces, and methods to format values. It also
contains extender methods to process strings and measure text size in an SVG/HTML
document.
TextProperties interface
This interface describes common properties of the text.
TypeScript
interface TextProperties {
text?: string;
fontFamily: string;
fontSize: string;
fontWeight?: string;
fontStyle?: string;
fontVariant?: string;
whiteSpace?: string;
}
measureSvgTextWidth
This function measures the width of the text with specific SVG text properties.
TypeScript
TypeScript
textMeasurementService.measureSvgTextWidth(textProperties);
// returns: 194.71875
measureSvgTextRect
This function returns a rect with the given SVG text properties.
TypeScript
TypeScript
textMeasurementService.measureSvgTextRect(textProperties);
measureSvgTextHeight
This function measures the height of the text with specific SVG text properties.
TypeScript
function measureSvgTextHeight(textProperties: TextProperties, text?:
string): number;
TypeScript
textMeasurementService.measureSvgTextHeight(textProperties);
// returns: 27
estimateSvgTextBaselineDelta
This function returns a baseline of specific SVG text properties.
TypeScript
Example:
TypeScript
textMeasurementService.estimateSvgTextBaselineDelta(textProperties);
// returns: 5
estimateSvgTextHeight
This function estimates the height of the text with specific SVG text properties.
TypeScript
TypeScript
textMeasurementService.estimateSvgTextHeight(textProperties);
// returns: 27
measureSvgTextElementWidth
This function measures the width of the svgElement.
TypeScript
TypeScript
import { textMeasurementService } from "powerbi-visuals-utils-
formattingutils";
// ...
svg.append("text")
.text("Microsoft PowerBI")
.attr({
"x": 25,
"y": 25
})
.style({
"font-family": "sans-serif",
"font-size": "24px"
});
textMeasurementService.measureSvgTextElementWidth(textElement.node());
// returns: 194.71875
getMeasurementProperties
This function fetches the text measurement properties of the given DOM element.
TypeScript
TypeScript
element.text("Microsoft PowerBI");
element.css({
"width": 500,
"height": 500,
"font-family": "sans-serif",
"font-size": "32em",
"font-weight": "bold",
"font-style": "italic",
"white-space": "nowrap"
});
textMeasurementService.getMeasurementProperties(element.get(0));
/* returns: {
fontFamily:"sans-serif",
fontSize: "32em",
fontStyle: "italic",
fontVariant: "",
fontWeight: "bold",
text: "Microsoft PowerBI",
whiteSpace: "nowrap"
}*/
getSvgMeasurementProperties
This function fetches the text measurement properties of the given SVG text element.
TypeScript
TypeScript
textMeasurementService.getSvgMeasurementProperties(textElement.node());
/* returns: {
"text": "Microsoft PowerBI",
"fontFamily": "sans-serif",
"fontSize": "24px",
"fontWeight": "normal",
"fontStyle": "normal",
"fontVariant": "normal",
"whiteSpace": "nowrap"
}*/
getDivElementWidth
This function returns the width of a div element.
TypeScript
TypeScript
textMeasurementService.getDivElementWidth(svg)
// returns: 150px
getTailoredTextOrDefault
Compares a label's text size to the available size, and renders ellipses when the available
size is smaller.
TypeScript
TypeScript
textMeasurementService.getTailoredTextOrDefault(textProperties, 100);
// returns: Micros...
String extensions
The module provides the following functions:
endsWith
This function checks if a string ends with a substring.
TypeScript
TypeScript
// returns: true
equalIgnoreCase
This function compares strings, ignoring case.
TypeScript
TypeScript
// returns: true
startsWith
This function checks if a string starts with a substring.
TypeScript
TypeScript
// returns: true
contains
This function checks if a string contains a specified substring.
TypeScript
// returns: true
isNullOrEmpty
Checks if a string is null or undefined or empty.
TypeScript
TypeScript
stringExtensions.isNullOrEmpty(null);
// returns: true
Value formatter
The module provides the following functions, interfaces, and classes:
IValueFormatter
This interface describes public methods and properties of the formatter.
TypeScript
interface IValueFormatter {
format(value: any): string;
displayUnit?: DisplayUnit;
options?: ValueFormatterOptions;
}
IValueFormatter.format
This method formats the specified value.
TypeScript
TypeScript
iValueFormatter.format(5678);
// returns: "5.68K"
TypeScript
iValueFormatter.format(1234567890);
// returns: "1234.57M"
TypeScript
iValueFormatter.format(1234567891236);
// returns: 1234.57bn
TypeScript
iValueFormatter.format(1234567891236);
// returns: 1.23T
TypeScript
iValueFormatter.format(1234567891236);
// returns: 1.234568E+012
TypeScript
iValueFormatter.format(0.54);
// returns: 54.00 %
TypeScript
iValueFormatter.format(date);
TypeScript
iValueFormatter.format(true);
// returns: True
TypeScript
// returns: 3.142
ValueFormatterOptions
This interface describes options of the IValueFormatter and options of create function.
TypeScript
interface ValueFormatterOptions {
/** The format string to use. */
format?: string;
/** The data value. */
value?: any;
/** The data value. */
value2?: any;
/** The number of ticks. */
tickCount?: any;
/** The display unit system to use */
displayUnitSystemType?: DisplayUnitSystemType;
/** True if we are formatting single values in isolation (e.g. card), as
opposed to multiple values with a common base (e.g. chart axes) */
formatSingleValues?: boolean;
/** True if we want to trim off unnecessary zeroes after the decimal and
remove a space before the % symbol */
allowFormatBeautification?: boolean;
/** Specifies the maximum number of decimal places to show*/
precision?: number;
/** Detect axis precision based on value */
detectAxisPrecision?: boolean;
/** Specifies the column type of the data value */
columnType?: ValueTypeDescriptor;
/** Specifies the culture */
cultureSelector?: string;
}
create
This method creates an instance of IValueFormatter.
TypeScript
import { valueFormatter } from "powerbi-visuals-utils-formattingutils";
import create = valueFormatter.create;
valueFormatter.create({});
format
Alternative way to format the value without creating IValueFormatter . Useful for cases
with dynamic formats string
TypeScript
const value = 12
const format = '¥ #,0'
valueFormatter.format(value, format);
Related content
Add the local language to your Power BI visual
Feedback
Was this page helpful? Yes No
Formatting model utils contains the classes, interfaces, and methods needed to build a
formatting settings model to populate the property panes (format and analytics panes)
of your Power BI custom visual.
TypeScript
constructor(options: VisualConstructorOptions) {
// ...
}
}
TypeScript
/**
* Build visual formatting settings model from metadata dataView
*
* @param dataViews metadata dataView object
* @returns visual formatting settings model
*/
populateFormattingSettingsModel<T extends Model>(typeClass: new () => T,
dataViews: powerbi.DataView[]): T;
/**
* Build formatting model by parsing formatting settings model object
*
* @returns powerbi visual formatting model
*/
buildFormattingModel(formattingSettingsModel: Model):
visuals.FormattingModel;
TypeScript
TypeScript
Adding slices to a formatting settings card puts all of these slices into one formatting
card.
Cards, Slices, and Groups can be hidden dynamically by setting the visible parameter
to false (true by default).
The card can populate either the formatting pane or analytics pane by setting the
analyticsPane parameter to true or false.
Example declaring formatting settings card, including one formatting settings group and
slice:
TypeScript
JSON
"objects": {
"myVisualCard": {
"properties": {
"myNumericSlice": {
"type": {
"numeric": true
}
},
"myAnotherNumericSlice": {
"type": {
"numeric": true
}
},
}
}
}
TypeScript
Each slice contains formatting properties. There's a long list of available formatting
properties types.
TypeScript
TypeScript
JSON
"objects": {
"myVisualCard": {
"properties": {
"myNumericSlice": {
"type": {
"numeric": true
}
}
}
}
}
TypeScript
TypeScript
TypeScript
constructor(options: VisualConstructorOptions) {
this.formattingSettingsService = new FormattingSettingsService();
// ...
}
TypeScript
TypeScript
public getFormattingModel(): powerbi.visuals.FormattingModel {
return
this.formattingSettingsService.buildFormattingModel(this.formattingSettings)
;
}
You can add selector to formatting property in its descriptor object. This example is
taken from the SampleBarChart for color custom visual data points using property
selectors:
TypeScript
new formattingSettings.ColorPicker({
name: "fill",
displayName: dataPoint.category,
value: { value: dataPoint.color },
selector:
dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataViewWil
dcardMatchingOption.InstancesAndTotals),
altConstantSelector: dataPoint.selectionId.getSelector(),
instanceKind: powerbi.VisualEnumerationInstanceKinds.ConstantOrRule
}
Localization
For more about the localization feature and to set up localization environment, see Add
the local language to your Power BI visual.
Init formatting settings service with localization manager in case localization is required
in your custom visual:
TypeScript
constructor(options: VisualConstructorOptions) {
const localizationManager = options.host.createLocalizationManager();
this.formattingSettingsService = new
FormattingSettingsService(localizationManager);
// ...
}
TypeScript
The HTMLSubSelectionHelper provides an easy way for your Power BI custom visual to emit subselections to Power BI, get
and render outlines.
HTMLSubSelectionHelper is a helper class intended to facilitate the creation and subsequent management of subselection
The utils exports CSS classes and attributes making it easier for the visual to define and maintain subselections.
7 Note
To define subselectable elements, we also need to add a class to each desired element.
ノ Expand table
subselectable Provides a selector for the HTMLSubSelectionHelper to find possible subselections yes
To define subselections for the visual, there are a few attributes that need to be added to the desired elements.
ノ Expand table
Format mode
When the visual enters format mode, You need to disable interactivity for the visual, as we expect the user to select the
visual and visual element to initiate formatting.
setFormatMode(isFormatMode: boolean): void - This method sets the format mode for the HTMLSubSelectionHelper,
If isFormatMode is true, the helper attaches relevant event listeners to the host element to enable format mode
functionality (subselecting, rendering outlines).
onVisualScroll(): void - Indicates to the HTMLSubSelectionHelper that scrolling is currently occurring. Scrolling should
remove outlines until scrolling is finished.
hideAllOutlines(suppressRender: boolean = false): void - hide all the outlines with respect to suppressRender.
createVisualSubSelectionForSingleObject(createVisualSubSelectionArgs: CreateVisualSubSelectionFromObjectArgs):
CustomVisualSubSelection - create CustomVisualSubSelection object from the createVisualSubSelectionArgs.
setDataForElement(el: HTMLElement | SVGElement, data: SubSelectionElementData): void - a static method that sets
data for the elements.
HtmlSubselectionHelperArgs
TypeScript
interface HtmlSubselectionHelperArgs {
/** Element which contains the items that can be sub-selected */
hostElement: HTMLElement; // The host element, the helper will attach the listeners to this element
subSelectionService: powerbi.extensibility.IVisualSubSelectionService;// subSelectionService which is
provided in powerbi-visuals-api
selectionIdCallback?: ((e: HTMLElement) => ISelectionId);// a callback that gets the selectionId for the
specific element
customOutlineCallback?: ((subSelection: CustomVisualSubSelection) =>
SubSelectionRegionOutlineFragment[]);// a callback to get custom outline for the specific subSelection
customElementCallback?: ((subSelection: CustomVisualSubSelection) => HTMLElement[]);
subSelectionMetadataCallback?: ((subSelectionElement: HTMLElement) => unknown);// a callback to attatch
any meta data to the subSelection.
}
SubSelectionStylesType
TypeScript
SubSelectableDirectEdit
TypeScript
interface SubSelectableDirectEdit {
reference: SliceFormattingModelReference;
style: SubSelectableDirectEditStyle;
displayValue?: string;
}
SubSelectionOutlineRestrictionType
TypeScript
To add restriction options to a specific element use the HTMLSubSelectionHelper setDataForElement with this data type, the
helper uses the data to update the outlines:
TypeScript
interface SubSelectionElementData {
outlineRestrictionOptions?: SubSelectionOutlineRestrictionOptions;
}
/** Options used to indicate if a restricting element should allow outlines more space to
* generate by adding padding or if the restricting element should constrict the outline more
* by adding a margin.
*/
export interface SubSelectionOutlineRestrictionOptions {
padding?: IOffset;
margin?: IOffset;
}
Example
In this example, we implement customOutlineCallback and selectionIdCallback : The following code is in Visual Code. We
have an object in the visual called arcElement . We want to render the outline when the element is hovered or subselected.
TypeScript
TypeScript
constructor(options: VisualConstructorOptions) {
…….
this.subSelectionHelper = HtmlSubSelectionHelper.createHtmlSubselectionHelper({
hostElement: options.element,
subSelectionService: options.host.subSelectionService,
selectionIdCallback: (e) => this.selectionIdCallback(e),
customOutlineCallback: (e) => this.ArcOutlines(e),
});
….
}
In update method of the visual add the following code to update the outlines of the subSeselection, update the state of the
format mode for the HTMLSubSelectionHelper and disable interactions that aren't for format mode if format mode is on:
TypeScript
if (this.formatMode) {// disabling interaction with the visual data in format mode
barSelectionMerged.on('click', null);
this.svg.on('click', null);
this.svg.on('contextmenu', null);
} else {
this.handleBarClick(barSelectionMerged);
this.handleClick(barSelectionMerged);
this.handleContextMenu();
}
this.subSelectionHelper.setFormatMode(options.formatMode);
const shouldUpdateSubSelection = options.type & powerbi.VisualUpdateType.Data
|| options.type & powerbi.VisualUpdateType.Resize
|| options.type & powerbi.VisualUpdateType.FormattingSubSelectionChange;
if (this.formatMode && shouldUpdateSubSelection) {
this.subSelectionHelper.updateOutlinesFromSubSelections(options.subSelections, true);
}
…
}
Related content
Subselection API
On-object formatting API
Feedback
Was this page helpful? Yes No
The DataViewUtils is a set of functions and classes to simplify parsing of the DataView
object for Power BI visuals.
Installation
To install the package, run the following command in the directory with your current
custom visual:
This command installs the package and adds a package as a dependency to your
package.json file.
DataViewWildcard
DataViewWildcard provides the createDataViewWildcardSelector function to support a
TotalsOnly) .
Example:
TypeScript
let selector =
dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataViewWil
dcardMatchingOption.InstancesAndTotals);
// returns {data: [{dataViewWildcard:{matchingOption: 0}}]};
DataRoleHelper
The DataRoleHelper provides functions to check roles of the dataView object.
The module provides the following functions:
getMeasureIndexOfRole
This function finds the measure by the role name and returns its index.
TypeScript
Example:
TypeScript
dataRoleHelper.getMeasureIndexOfRole(columnGroup, "product");
// returns: 1
getCategoryIndexOfRole
This function finds the category by the role name and returns its index.
TypeScript
Example:
TypeScript
dataRoleHelper.getCategoryIndexOfRole(categoryGroup, "product");
// returns: 1
hasRole
This function checks if the provided role is defined in the metadata.
TypeScript
TypeScript
DataRoleHelper.hasRole(metadata, "company");
// returns: true
hasRoleInDataView
This function checks if the provided role is defined in the dataView.
TypeScript
Example:
TypeScript
DataRoleHelper.hasRoleInDataView(dataView, "product");
// returns: true
hasRoleInValueColumn
This function checks if the provided role is defined in the value column.
TypeScript
Example:
TypeScript
dataRoleHelper.hasRoleInValueColumn(valueColumn, "company");
// returns: true
DataViewObjects
The DataViewObjects provides functions to extract the values of the objects.
TypeScript
Example:
TypeScript
dataViewObjects.getValue(objects, property);
// returns: Power
getObject
This function returns an object from specified objects.
TypeScript
Example:
TypeScript
import { dataViewObjects } from "powerbi-visuals-utils-dataviewutils";
dataViewObjects.getObject(objects, "microsoft");
/* returns: {
"bi": "Power",
"windows": 5
}*/
getFillColor
This function returns a solid color of the objects.
TypeScript
Example:
TypeScript
dataViewObjects.getFillColor(objects, property);
// returns: yellow
getCommonValue
This universal function retrieves the color or value of a specific object.
TypeScript
Example:
TypeScript
DataViewObject
The DataViewObject provides functions to extract the value of the object.
getValue
This function returns a value of the object by the property name.
TypeScript
Example:
TypeScript
dataViewObject.getValue(object, "microsoft");
// returns: Power BI
getFillColorByPropertyName
This function returns a solid color of the object by the property name.
TypeScript
Example:
TypeScript
dataViewObject.getFillColorByPropertyName(object, "fillColor");
// returns: green
converterHelper
The converterHelper provides functions to check properties of the dataView.
categoryIsAlsoSeriesRole
This function checks if the category is also a series.
TypeScript
Example:
TypeScript
// returns: true
getSeriesName
This function returns a name of the series.
TypeScript
Example:
TypeScript
converterHelper.getSeriesName(metadata);
// returns: Power BI
isImageUrlColumn
This function checks if the column contains an image URL.
TypeScript
function isImageUrlColumn(column: DataViewMetadataColumn): boolean;
Example:
TypeScript
converterHelper.isImageUrlColumn(metadata);
// returns: true
isWebUrlColumn
This function checks if the column contains a web URL.
TypeScript
Example:
TypeScript
converterHelper.isWebUrlColumn(metadata);
// returns: true
hasImageUrlColumn
This function checks if the dataView has a column with an image URL.
TypeScript
Example:
TypeScript
converterHelper.hasImageUrlColumn(dataView);
// returns: true
DataViewObjectsParser
The DataViewObjectsParser provides the simplest way to parse the properties of the
formatting panel.
getDefault
This static method returns an instance of DataViewObjectsParser.
TypeScript
Example:
TypeScript
dataViewObjectsParser.getDefault();
parse
This method parses the properties of the formatting panel and returns an instance of
DataViewObjectsParser .
TypeScript
Example:
TypeScript
/**
* This class describes formatting panel properties.
* Name of the property should match its name described in the capabilities.
*/
class DataPointProperties {
public fillColor: string = "red"; // This value is a default value of
the property.
}
enumerateObjectInstances
) Important
TypeScript
static enumerateObjectInstances(dataViewObjectParser:
dataViewObjectsParser.DataViewObjectsParser, options:
EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration;
Example:
TypeScript
/**
* This class describes formatting panel properties.
* Name of the property should match its name described in the capabilities.
*/
class DataPointProperties {
public fillColor: string = "red";
}
/**
* This method will be executed only if the formatting panel is open.
*/
public enumerateObjectInstances(options:
EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
return
PropertiesParser.enumerateObjectInstances(this.propertiesParser, options);
}
}
Feedback
Was this page helpful? Yes No
ChartUtils is a set of interfaces and methods for creating axis, data labels, and legends in
Power BI Visuals.
Installation
To install the package, you should run the following command in the directory with your
current visual:
Bash
Axis Helper
The axis helper ( axis object in utils) provides functions to simplify manipulations that
have an axis.
getRecommendedNumberOfTicksForXAxis
This function returns the recommended number of ticks according to the width of chart.
TypeScript
Example:
TypeScript
// returns: 8
getRecommendedNumberOfTicksForYAxis
This function returns the recommended number of ticks according to the height of
chart.
TypeScript
Example:
TypeScript
// returns: 3
getBestNumberOfTicks
Gets the optimal number of ticks based on minimum value, maximum value, measure
metadata, and max tick count.
TypeScript
function getBestNumberOfTicks(
min: number,
max: number,
valuesMetadata: DataViewMetadataColumn[],
maxTickCount: number,
isDateTime?: boolean
): number;
Example:
TypeScript
// returns: 4
getTickLabelMargins
This function returns the margins for tick labels.
TypeScript
function getTickLabelMargins(
viewport: IViewport,
yMarginLimit: number,
textWidthMeasurer: ITextAsSVGMeasurer,
textHeightMeasurer: ITextAsSVGMeasurer,
axes: CartesianAxisProperties,
bottomMarginLimit: number,
properties: TextProperties,
scrollbarVisible?: boolean,
showOnRight?: boolean,
renderXAxis?: boolean,
renderY1Axis?: boolean,
renderY2Axis?: boolean
): TickLabelMargins;
Example:
TypeScript
axis.getTickLabelMargins(
plotArea,
marginLimits.left,
TextMeasurementService.measureSvgTextWidth,
TextMeasurementService.estimateSvgTextHeight,
axes,
marginLimits.bottom,
textProperties,
/*scrolling*/ false,
showY1OnRight,
renderXAxis,
renderY1Axis,
renderY2Axis
);
isOrdinal
Checks if a string is null, undefined or empty.
TypeScript
Example:
TypeScript
// returns: true
isDateTime
Checks if a value is of the DateTime type.
TypeScript
Example:
TypeScript
getCategoryThickness
Uses the D3 scale to get the actual category thickness.
TypeScript
Example:
TypeScript
invertOrdinalScale
This function inverts the ordinal scale. If x < scale.range()[0], then scale.domain()[0] is
returned. Otherwise, it returns the greatest item in scale.domain() that's <= x.
TypeScript
Example:
TypeScript
axis.invertOrdinalScale(ordinalScale, 49);
// returns: 4
findClosestXAxisIndex
This function finds and returns the closest x-axis index.
TypeScript
function findClosestXAxisIndex(
categoryValue: number,
categoryAxisValues: AxisHelperCategoryDataPoint[]
): number;
Example:
TypeScript
/**
* Finds the index of the category of the given x coordinate given.
* pointX is in non-scaled screen-space, and offsetX is in render-space.
* offsetX does not need any scaling adjustment.
* @param {number} pointX The mouse coordinate in screen-space, without
scaling applied
* @param {number} offsetX Any left offset in d3.scale render-space
* @return {number}
*/
private findIndex(pointX: number, offsetX?: number): number {
// we are using mouse coordinates that do not know about any potential
CSS transform scale
let xScale = this.scaleDetector.getScale().x;
if (!Double.equalWithPrecision(xScale, 1.0, 0.00001)) {
pointX = pointX / xScale;
}
if (offsetX) {
pointX += offsetX;
}
return index;
}
diffScaled
This function computes and returns a diff of values in the scale.
TypeScript
function diffScaled(
scale: d3.scale.Linear<any, any>,
value1: any,
value2: any
): number;
Example:
TypeScript
scale = d3.scale.linear()
.range(range)
.domain(domain);
// returns: 0
createDomain
This function creates a domain of values for an axis.
TypeScript
function createDomain(
data: any[],
axisType: ValueTypeDescriptor,
isScalar: boolean,
forcedScalarDomain: any[],
ensureDomain?: NumberRange
): number[];
Example:
TypeScript
var cartesianSeries = [
{
data: [
{ categoryValue: 7, value: 11, categoryIndex: 0, seriesIndex: 0 },
{
categoryValue: 9,
value: 9,
categoryIndex: 1,
seriesIndex: 0
},
{
categoryValue: 15,
value: 6,
categoryIndex: 2,
seriesIndex: 0
},
{ categoryValue: 22, value: 7, categoryIndex: 3, seriesIndex: 0 }
]
}
];
// returns: [0, 1, 2, 3]
getCategoryValueType
This function gets the ValueType of a category column. Default is Text if the type isn't
present.
TypeScript
function getCategoryValueType(
data: any[],
axisType: ValueTypeDescriptor,
isScalar: boolean,
forcedScalarDomain: any[],
ensureDomain?: NumberRange
): number[];
Example:
TypeScript
var cartesianSeries = [
{
data: [
{ categoryValue: 7, value: 11, categoryIndex: 0, seriesIndex: 0 },
{
categoryValue: 9,
value: 9,
categoryIndex: 1,
seriesIndex: 0
},
{
categoryValue: 15,
value: 6,
categoryIndex: 2,
seriesIndex: 0
},
{ categoryValue: 22, value: 7, categoryIndex: 3, seriesIndex: 0 }
]
}
];
axis.getCategoryValueType(
cartesianSeries,
ValueType.fromDescriptor({ text: true }),
false,
[]
);
// returns: [0, 1, 2, 3]
createAxis
This function creates a D3 axis including scale. Can be vertical or horizontal, and either
datetime, numeric, or text.
TypeScript
function createAxis(options: CreateAxisOptions): IAxisProperties;
Example:
TypeScript
var os = axis.createAxis({
pixelSpan: 100,
dataDomain: [dataPercent[0], dataPercent[2]],
metaDataColumn: metaDataColumnPercent,
formatString: valueFormatter.getFormatString(
metaDataColumnPercent,
formatStringProp
),
outerPadding: 0.5,
isScalar: true,
isVertical: true
});
applyCustomizedDomain
This function sets a customized domain, but it doesn't change when nothing is set.
TypeScript
TypeScript
axis.applyCustomizedDomain(customizedDomain, existingDomain);
combineDomain
This function combines the forced domain with the actual domain if one of the values
was set. The forcedDomain is in first priority. Extends the domain if any reference point
requires it.
TypeScript
function combineDomain(
forcedDomain: any[],
domain: any[],
ensureDomain?: NumberRange
): any[];
Example:
TypeScript
powerOfTen
This function indicates whether the number is power of 10.
TypeScript
Example:
TypeScript
axis.powerOfTen(10);
// returns: true
DataLabelManager
The DataLabelManager helps to create and maintain labels. It arranges label elements
using the anchor point or rectangle. Collisions can be automatically detected to
reposition or hide elements.
hideCollidedLabels
This method arranges the labels position and visibility on the canvas according to label
sizes and overlapping.
TypeScript
function hideCollidedLabels(
viewport: IViewport,
data: any[],
layout: any,
addTransform: boolean = false
hideCollidedLabels?: boolean
): LabelEnabledDataPoint[];
Example:
TypeScript
let dataLabelManager = new DataLabelManager();
let filteredData = dataLabelManager.hideCollidedLabels(
this.viewport,
values,
labelLayout,
true,
true
);
IsValid
This static method checks if the provided rectangle is valid, that is, it has positive width
and height.
TypeScript
Example:
TypeScript
let rectangle = {
left: 150,
top: 130,
width: 120,
height: 110
};
DataLabelManager.isValid(rectangle);
// returns: true
DataLabelUtils
The DataLabelUtils provides utils to manipulate data labels.
getLabelPrecision
This function calculates precision from a provided format.
TypeScript
function getLabelPrecision(precision: number, format: string): number;
getLabelFormattedText
This function returns format precision from the provided format.
TypeScript
Example:
TypeScript
dataLabelUtils.getLabelFormattedText(options);
enumerateDataLabels
This function returns VisualObjectInstance for data labels.
TypeScript
function enumerateDataLabels(
options: VisualDataLabelsSettingsOptions
): VisualObjectInstance;
enumerateCategoryLabels
This function adds VisualObjectInstance for Category data labels to an enumeration
object.
TypeScript
function enumerateCategoryLabels(
enumeration: VisualObjectInstanceEnumerationObject,
dataLabelsSettings: VisualDataLabelsSettings,
withFill: boolean,
isShowCategory: boolean = false,
fontSize?: number
): void;
createColumnFormatterCacheManager
This function returns the Cache Manager that provides quick access to formatted labels.
TypeScript
Example:
TypeScript
labelSettings.displayUnits = 1000000;
labelSettings.precision = 1;
// formattedValue == "0.2M"
Legend service
The Legend service provides helper interfaces for creating and managing Power BI
legends for Power BI visuals.
createLegend
This helper function simplifies Power BI Custom Visual legend creation.
TypeScript
function createLegend(
legendParentElement: HTMLElement, // top visual element, container in
which legend will be created
interactive: boolean, // indicates that legend should be interactive
interactivityService: IInteractivityService, // reference to
IInteractivityService interface which need to create legend click events
isScrollable: boolean = false, // indicates that legend could be
scrollable or not
legendPosition: LegendPosition = LegendPosition.Top // Position of the
legend inside of legendParentElement container
): ILegend;
Example:
TypeScript
if (this.behavior) {
this.interactivityService =
createInteractivityService(hostServices);
}
this.legend = createLegend(
element,
options.interactivity && options.interactivity.isInteractiveLegend,
this.interactivityService,
true);
}
ILegend
This Interface implements all methods necessary for legend creation.
TypeScript
drawLegend
This function measures the height of the text with the given SVG text properties.
TypeScript
Example:
TypeScript
this.legend.drawLegend(legendData, this.parentViewport);
} else {
this.legend.changeOrientation(LegendPosition.Top);
this.legend.drawLegend({ dataPoints: [] }, this.parentViewport);
}
}
}
Related content
Power BI visuals interactivity utils
Feedback
Was this page helpful? Yes No
This article will help you to install, import, and use color utils. Learn how to use color
utils to apply themes and palettes on a Power BI visual's data points.
Prerequisites
To use the package, install:
Installation
To install the package, you should run the following command in the directory with your
current visual:
Bash
This command installs the package and adds a package as a dependency to your
package.json file.
Usage
To use interactivity utils, you have to import the required component in the source code
of the visual.
TypeScript
Learn how to install and use the colorUtils in your Power BI visuals:
[Usage Guide] The Usage Guide describes a public API of the package. It provides
a description and examples for each public interface.
This package contains the following classes and modules:
ColorHelper
The ColorHelper class provides the following functions and methods:
getColorForSeriesValue
This method gets the color for a specific series value. If no explicit color or default color
has been set, then the color is allocated from the color scale for this series.
TypeScript
getColorForSeriesValue example
TypeScript
constructor(options: VisualConstructorOptions) {
this.colorPalette = options.host.colorPalette;
}
getColorForMeasure
This method gets the color for a specific measure.
TypeScript
TypeScript
constructor(options: VisualConstructorOptions) {
this.colorPalette = options.host.colorPalette;
}
static normalizeSelector
This method returns the normalized selector.
TypeScript
TypeScript
getThemeColor
TypeScript
getHighContrastColor
TypeScript
TypeScript
ColorUtils
The module provides the following functions:
hexToRGBString
rotate
parseColorString
calculateHighlightColor
createLinearColorScale
shadeColor
rgbBlend
channelBlend
hexBlend
hexToRGBString
Converts a hex color to an RGB string.
TypeScript
hexToRGBString example
TypeScript
hexToRGBString('#112233');
// returns: "rgb(17,34,51)"
rotate
Rotates RGB color.
TypeScript
rotate example
TypeScript
parseColorString
Parses any color string to RGB format.
TypeScript
parseColorString example
TypeScript
parseColorString('#09f');
// returns: {R: 0, G: 153, B: 255 }
parseColorString('rgba(1, 2, 3, 1.0)');
// returns: {R: 1, G: 2, B: 3, A: 1.0 }
calculateHighlightColor
Calculates the highlight color from the rgbColor based on the lumianceThreshold and
delta.
TypeScript
function calculateHighlightColor(rgbColor: RgbColor, lumianceThreshold:
number, delta: number): string
calculateHighlightColor example
TypeScript
// returns: '#CCCC00'
createLinearColorScale
Returns a linear color scale for a specific domain of numbers.
TypeScript
createLinearColorScale example
TypeScript
shadeColor
Converts a string hex expression to a number, and calculates the percentage and R, G, B
channels. Applies the percentage for each channel and returns the hex value as a string
with a pound sign.
TypeScript
shadeColor example
TypeScript
rgbBlend
Overlays a color with opacity over a background color. Any alpha-channel is ignored.
TypeScript
rgbBlend example
TypeScript
channelBlend
Blends a single channel for two colors.
TypeScript
function channelBlend(foreChannel: number, opacity: number, backChannel:
number): number
channelBlend example
TypeScript
hexBlend
Overlays a color with opacity over a background color.
TypeScript
hexBlend example
TypeScript
Feedback
Was this page helpful? Yes No
SVGUtils is a set of functions and classes to simplify SVG manipulations for Power BI
visuals.
Installation
To install the package, you should run the following command in the directory with your
current visual:
Bash
CssConstants
The CssConstants module provides the special function and interface to work with class
selectors.
ClassAndSelector
This interface describes common properties of the class selector.
TypeScript
interface ClassAndSelector {
class: string;
selector: string;
}
createClassAndSelector
This function creates an instance of ClassAndSelector with the name of the class.
TypeScript
function createClassAndSelector(className: string): ClassAndSelector;
Example:
TypeScript
manipulation
The manipulation method provides some special functions to generate strings that you
can use with the SVG transform property.
translate
This function creates a translate string for use with the SVG transform property.
TypeScript
Example:
TypeScript
manipulation.translate(100, 100);
// returns: translate(100,100)
translateXWithPixels
This function creates a translateX string for use with the SVG transform property.
TypeScript
Example:
TypeScript
manipulation.translateXWithPixels(100);
// returns: translateX(100px)
translateWithPixels
This function creates a translate string for use with the SVG transform property.
TypeScript
Example:
TypeScript
manipulation.translateWithPixels(100, 100);
// returns: translate(100px,100px)
translateAndRotate
This function creates a translate-rotate string for use with the SVG transform property.
TypeScript
function translateAndRotate(
x: number,
y: number,
px: number,
py: number,
angle: number
): string;
Example:
TypeScript
scale
This function creates a scale string for use in a CSS transform property.
TypeScript
Example:
TypeScript
manipulation.scale(50);
// returns: scale(50)
transformOrigin
This function creates a transform-origin string for use in a CSS transform-origin
property.
TypeScript
TypeScript
manipulation.transformOrigin(5, 5);
// returns: 5 5
flushAllD3Transitions
This function forces every transition of D3 to complete.
TypeScript
Example:
TypeScript
manipulation.flushAllD3Transitions();
parseTranslateTransform
This function parses the transform string with value "translate(x,y)".
TypeScript
Example:
TypeScript
createArrow
This function creates an arrow.
TypeScript
function createArrow(
width: number,
height: number,
rotate: number
): { path: string; transform: string };
Example:
TypeScript
/* returns: {
"path": "M0 0L0 20L10 10 Z",
"transform": "rotate(5 5 10)"
}*/
Rect
The Rect module provides some special functions to manipulate rectangles.
getOffset
This function returns an offset of the rectangle.
TypeScript
TypeScript
Rect.getOffset({ left: 25, top: 25, width: 100, height: 100 });
/* returns: {
x: 25,
y: 25
}*/
getSize
This function returns the size of the rectangle.
TypeScript
Example:
TypeScript
Rect.getSize({ left: 25, top: 25, width: 100, height: 100 });
/* returns: {
width: 100,
height: 100
}*/
setSize
This function modifies the size of the rectangle.
TypeScript
TypeScript
let rectangle = { left: 25, top: 25, width: 100, height: 100 };
// rectangle === { left: 25, top: 25, width: 250, height: 250 }
right
This function returns a right position of the rectangle.
TypeScript
Example:
TypeScript
Rect.right({ left: 25, top: 25, width: 100, height: 100 });
// returns: 125
bottom
This function returns a bottom position of the rectangle.
TypeScript
Example:
TypeScript
import { shapes } from "powerbi-visuals-utils-svgutils";
import Rect = shapes.Rect;
// ...
Rect.bottom({ left: 25, top: 25, width: 100, height: 100 });
// returns: 125
topLeft
This function returns a top-left position of the rectangle.
TypeScript
Example:
TypeScript
Rect.topLeft({ left: 25, top: 25, width: 100, height: 100 });
// returns: { x: 25, y: 25 }
topRight
This function returns a top-right position of the rectangle.
TypeScript
Example:
TypeScript
Rect.topRight({ left: 25, top: 25, width: 100, height: 100 });
// returns: { x: 125, y: 25 }
bottomLeft
This function returns a bottom-left position of the rectangle.
TypeScript
Example:
TypeScript
Rect.bottomLeft({ left: 25, top: 25, width: 100, height: 100 });
bottomRight
This function returns a bottom-right position of the rectangle.
TypeScript
Example:
TypeScript
Rect.bottomRight({ left: 25, top: 25, width: 100, height: 100 });
clone
This function creates a copy of the rectangle.
TypeScript
Example:
TypeScript
Rect.clone({ left: 25, top: 25, width: 100, height: 100 });
/* returns: {
left: 25, top: 25, width: 100, height: 100}
*/
toString
This function converts the rectangle to a string.
TypeScript
Example:
TypeScript
Rect.toString({ left: 25, top: 25, width: 100, height: 100 });
offset
This function applies an offset to the rectangle.
TypeScript
function offset(rect: IRect, offsetX: number, offsetY: number): IRect;
Example:
TypeScript
Rect.offset({ left: 25, top: 25, width: 100, height: 100 }, 50, 50);
/* returns: {
left: 75,
top: 75,
width: 100,
height: 100
}*/
add
This function adds the first rectangle to the second rectangle.
TypeScript
Example:
TypeScript
Rect.add(
{ left: 25, top: 25, width: 100, height: 100 },
{ left: 50, top: 50, width: 75, height: 75 }
);
/* returns: {
left: 75,
top: 75,
height: 175,
width: 175
}*/
getClosestPoint
This function returns the closest point on the rectangle to a specific point.
TypeScript
Example:
TypeScript
/* returns: {
x: 50,
y: 50
}*/
equal
This function compares rectangles and returns true if they're the same.
TypeScript
Example:
TypeScript
Rect.equal(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 50, top: 50, width: 100, height: 100 }
);
// returns: false
equalWithPrecision
This function compares rectangles by considering precision of the values.
TypeScript
Example:
TypeScript
Rect.equalWithPrecision(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 50, top: 50, width: 100, height: 100 }
);
// returns: false
isEmpty
This function checks if a rectangle is empty.
TypeScript
Example:
TypeScript
// returns: true
containsPoint
This function checks if a rectangle contains a specific point.
TypeScript
Example:
TypeScript
Rect.containsPoint(
{ left: 0, top: 0, width: 100, height: 100 },
{ x: 50, y: 50 }
);
// returns: true
isIntersecting
This function checks if rectangles are intersecting.
TypeScript
Example:
TypeScript
Rect.isIntersecting(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 0, top: 0, width: 50, height: 50 }
);
// returns: true
intersect
This function returns an intersection of rectangles.
TypeScript
Example:
TypeScript
Rect.intersect(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 0, top: 0, width: 50, height: 50 }
);
/* returns: {
left: 0,
top: 0,
width: 50,
height: 50
}*/
combine
This function combines rectangles.
TypeScript
Example:
TypeScript
Rect.combine(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 0, top: 0, width: 50, height: 120 }
);
/* returns: {
left: 0,
top: 0,
width: 100,
height: 120
}*/
getCentroid
This function returns a center point of the rectangle.
TypeScript
Example:
TypeScript
/* returns: {
x: 50,
y: 50
}*/
Feedback
Was this page helpful? Yes No
TypeUtils is a set of functions and classes to extend the basic types for Power BI visuals.
Installation
To install the package, run the following command in the directory with your current
custom visual:
This command installs the package and adds a package as a dependency to your
package.json file.
Double
The Double module provides abilities to manipulate precision of the numbers.
pow10
This function returns power of 10.
TypeScript
Example:
TypeScript
double.pow10(25);
// returns: 1e+25
log10
This function returns a 10 base logarithm of the number.
TypeScript
Example:
TypeScript
double.log10(25);
// returns: 1
getPrecision
This function returns a power of 10 representing precision of the number.
TypeScript
Example:
TypeScript
double.getPrecision(562344, 6);
// returns: 0.1
equalWithPrecision
This function checks if a delta between two numbers is less than provided precision.
TypeScript
TypeScript
// returns: true
lessWithPrecision
This function checks if the first value is less than the second value.
TypeScript
Example:
TypeScript
double.lessWithPrecision(0.995, 1, 0.001);
// returns: true
lessOrEqualWithPrecision
This function checks if the first value is less than or equal to the second value.
TypeScript
Example:
TypeScript
import { double } from "powerbi-visuals-utils-typeutils";
// ...
double.lessOrEqualWithPrecision(1.005, 1, 0.01);
// returns: true
greaterWithPrecision
This function checks if the first value is greater than the second value.
TypeScript
Example:
TypeScript
// returns: false
greaterOrEqualWithPrecision
This function checks if the first value is greater than or equal to the second value.
TypeScript
Example:
TypeScript
floorWithPrecision
This function floors the number with the provided precision.
TypeScript
Example:
TypeScript
double.floorWithPrecision(5.96, 0.001);
// returns: 5
ceilWithPrecision
This function ceils the number with the provided precision.
TypeScript
Example:
TypeScript
double.ceilWithPrecision(5.06, 0.001);
// returns: 6
floorToPrecision
This function floors the number to the provided precision.
TypeScript
Example:
TypeScript
double.floorToPrecision(5.96, 0.1);
// returns: 5.9
ceilToPrecision
This function ceils the number to the provided precision.
TypeScript
Example:
TypeScript
double.ceilToPrecision(-506, 10);
// returns: -500
roundToPrecision
This function rounds the number to the provided precision.
TypeScript
TypeScript
double.roundToPrecision(596, 10);
// returns: 600
ensureInRange
This function returns a number that is between min and max.
TypeScript
Example:
TypeScript
// returns: -10
round
This function rounds the number.
TypeScript
Example:
TypeScript
// returns: 27
removeDecimalNoise
This function rounds the number to eliminate some decimal spaces.
TypeScript
Example:
TypeScript
double.removeDecimalNoise(21.493000000000002);
// returns: 21.493
isInteger
This function checks if the number is an integer.
TypeScript
Example:
TypeScript
double.isInteger(21.493000000000002);
// returns: false
toIncrement
This function increments the number by the provided number and returns the rounded
number.
TypeScript
Example:
TypeScript
double.toIncrement(0.6383723, 0.05);
// returns: 0.65
Prototype
The Prototype module provides the ability to inherit objects.
inherit
This function returns a new object with the provided object as its prototype.
TypeScript
Example:
TypeScript
prototype.inherit(base);
/* returns: {
__proto__: {
Microsoft: "Power BI"
}
}*/
inheritSingle
This function returns a new object with the provided object as its prototype if, and only
if, the prototype hasn't been set.
TypeScript
Example:
TypeScript
prototype.inheritSingle(base);
/* returns: {
__proto__: {
Microsoft: "Power BI"
}
}*/
PixelConverter
The PixelConverter module provides the ability to convert pixels to points, and points
to pixels.
toString
This function converts the pixel value to a string.
TypeScript
function toString(px: number): string;
Example:
TypeScript
pixelConverter.toString(25);
// returns: 25px
fromPoint
This function converts the provided point value to the pixel value and returns the string
interpretation.
TypeScript
Example:
TypeScript
pixelConverter.fromPoint(8);
// returns: 33.33333333333333px
fromPointToPixel
This function converts the provided point value to the pixel value.
TypeScript
Example:
TypeScript
pixelConverter.fromPointToPixel(8);
// returns: 10.666666666666666
toPoint
This function converts the pixel value to the point value.
TypeScript
Example:
TypeScript
pixelConverter.toPoint(8);
// returns: 6
Feedback
Was this page helpful? Yes No
This article helps you install, import, and use the Power BI visuals test utils. These test
utilities can be used for unit testing and include mocks and methods for elements, such
as data views, selections, and color schemas.
Prerequisites
To use this package, install:
Installation
To install test utils and add its dependency to your package.json, run the following
command from your Power BI visuals directory:
Bash
The following provide descriptions and examples on the test utils public API.
VisualBuilderBase
Used by VisualBuilder in unit tests with the most frequently used methods, build ,
update , and updateRenderTimeout .
TypeScript
7 Note
For more examples, see Writing VisualBuilderBase unit tests and a Real usage
VisualBuilderBase scenario .
DataViewBuilder
Used by TestDataViewBuilder, this module provides a CategoricalDataViewBuilder class
used in the createCategoricalDataViewBuilder method. It also specifies interfaces and
methods required for working with mocked DataView in unit tests.
withValues adds static series columns, and withGroupedValues adds dynamic series
columns.
Don't apply both dynamic series and static series in a visual DataViewCategorical.
You can only use them both in the DataViewCategorical query, where
DataViewTransform is expected to split them into separate visual
DataViewCategorical objects.
including both dynamic and static series when building the visual DataView.
TypeScript
class CategoricalDataViewBuilder implements IDataViewBuilderCategorical {
withCategory(options: DataViewBuilderCategoryColumnOptions):
IDataViewBuilderCategorical;
withCategories(categories: DataViewCategoryColumn[]):
IDataViewBuilderCategorical;
withValues(options: DataViewBuilderValuesOptions):
IDataViewBuilderCategorical;
withGroupedValues(options: DataViewBuilderGroupedValuesOptions):
IDataViewBuilderCategorical;
build(): DataView;
}
TestDataViewBuilder
Used for VisualData creation in unit tests. When data is placed in data-field buckets,
Power BI produces a categorical DataView object based on the data. The
TestDataViewBuilder helps simulate categorical DataView creation.
TypeScript
The following lists the most frequently used interfaces when creating a testDataView :
TypeScript
interface DataViewBuilderColumnOptions {
source: DataViewMetadataColumn;
}
interface DataViewBuilderSeriesData {
values: PrimitiveValue[];
highlights?: PrimitiveValue[];
/** Client-computed maximum value for a column. */
maxLocal?: any;
/** Client-computed maximum value for a column. */
minLocal?: any;
}
interface DataViewBuilderColumnIdentitySource {
fields: any[];
identities?: CustomVisualOpaqueIdentity[];
}
7 Note
For more examples, see Writing TestDataViewBuilder unit tests and a Real usage
TestDataViewBuilder scenario .
Mocks
MockIVisualHost
Implements IVisualHost to test Power BI visuals without external dependencies, such as
the Power BI framework.
TypeScript
import VisualObjectInstancesToPersist =
powerbi.VisualObjectInstancesToPersist;
import ISelectionIdBuilder = powerbi.visuals.ISelectionIdBuilder;
import ISelectionManager = powerbi.extensibility.ISelectionManager;
import IColorPalette = powerbi.extensibility.IColorPalette;
import IVisualEventService = powerbi.extensibility.IVisualEventService;
import ITooltipService = powerbi.extensibility.ITooltipService;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
MockIVisualHost.
TypeScript
Example:
TypeScript
) Important
MockIColorPalette
Implements IColorPalette to test Power BI visuals without external dependencies, such
as the Power BI framework.
TypeScript
MockIColorPalette.
TypeScript
Example:
TypeScript
) Important
MockISelectionId
Implements ISelectionId to test Power BI visuals without external dependencies, such as
the Power BI framework.
TypeScript
MockISelectionId.
TypeScript
TypeScript
7 Note
MockISelectionIdBuilder
Implements ISelectionIdBuilder to test Power BI visuals without external dependencies,
such as the Power BI framework.
TypeScript
actually MockISelectionIdBuilder.
TypeScript
TypeScript
7 Note
MockISelectionManager
Implements ISelectionManager to test Power BI visuals without external dependencies,
such as the Power BI framework.
TypeScript
actually MockISelectionManager.
TypeScript
TypeScript
7 Note
MockILocale
Sets the locale and changes it for your needs during a unit testing process.
TypeScript
class MockILocale {
constructor(locales?: Object): void; // Default locales are en-US and
ru-RU
locale(key: string): void;// setter property
locale(): string; // getter property
}
TypeScript
MockITooltipService
Simulates TooltipService and calls it for your needs during a unit testing process.
TypeScript
TypeScript
MockIAllowInteractions
TypeScript
MockIAllowInteractions.
TypeScript
MockILocalizationManager
Provides basic abilities of LocalizationManager, which are needed for unit testing.
TypeScript
TypeScript
Example:
TypeScript
MockITelemetryService
Simulates TelemetryService usage.
TypeScript
MockIAuthenticationService
Simulates the work of AuthenticationService by providing a mocked Microsoft Entra
token.
TypeScript
TypeScript
function createAuthenticationService(token?: string):
IAuthenticationService;
MockIStorageService
Allows you to use ILocalVisualStorageService with the same behavior as LocalStorage.
TypeScript
TypeScript
MockIEventService
TypeScript
actually MockIEventService.
TypeScript
TypeScript
TypeScript
Example:
TypeScript
TypeScript
JSON
TypeScript
parseColorString parses color from the input string and returns it in specified
interface RgbColor.
TypeScript
TypeScript
function getRandomNumber(
min: number,
max: number,
exceptionList?: number[],
changeResult: (value: any) => number = x => x): number
TypeScript
TypeScript
function clickElement(element: JQuery, ctrlKey: boolean = false): void
TypeScript
TypeScript
TypeScript
TypeScript
function createMouseEvent(
mouseEventType: MouseEventType,
eventType: ClickEventType,
x: number,
y: number,
button: number = 0): MouseEvent
createTouchEndEvent
TypeScript
createTouchMoveEvent
TypeScript
TypeScript
TypeScript
function flushAllD3Transitions()
7 Note
These flickers are more noticeable on IE and with a large number of webviews
and aren't recommended for iOS.
By flushing the timer queue at the end of the first event loop, you can run any
zero-delay transitions immediately and avoid the flicker.
TypeScript
Helper interfaces
The following interface and enumerations are used in the helper function.
TypeScript
interface RgbColor {
R: number;
G: number;
B: number;
A?: number;
}
enum ClickEventType {
Default = 0,
CtrlKey = 1,
AltKey = 2,
ShiftKey = 4,
MetaKey = 8,
}
enum MouseEventType {
click,
mousedown,
mouseup,
mouseover,
mousemove,
mouseout,
}
Related content
To write unit tests for webpack-based Power BI visuals, and unit test with karma and
jasmine , see Tutorial: Add unit tests for Power BI visual projects.
Feedback
Was this page helpful? Yes No
This article will help you to install, import, and use tooltip utils. This util is useful for
tooltip customizations in Power BI visuals.
Prerequisites
To use the package, you need:
Installation
To install the package, you should run the following command in the directory with your
current visual:
Bash
This command installs the package and adds a package as a dependency to your
package.json file.
Usage
The Usage Guide describes a public API of the package. You will find a description
and some examples for each public interface of the package.
This package provides you with a way to create TooltipServiceWrapper and methods to
help handle tooltip actions. It uses tooltip interfaces - ITooltipServiceWrapper ,
TooltipEventArgs , TooltipEnabledDataPoint .
ITooltipServiceWrapper
addTooltip
hide
Interfaces
TooltipEventArgs
TooltipEnabledDataPoint
TooltipServiceWrapperOptions
Touch events
createTooltipServiceWrapper
TypeScript
Example:
TypeScript
constructor(options: VisualConstructorOptions) {
createTooltipServiceWrapper(
options.host.tooltipService,
options.element);
TypeScript
interface ITooltipServiceWrapper {
addTooltip<T>(selection: d3.Selection<any, any, any, any>,
getTooltipInfoDelegate: (args: TooltipEventArgs<T>) =>
powerbi.extensibility.VisualTooltipDataItem[], getDataPointIdentity?: (args:
TooltipEventArgs<T>) => powerbi.visuals.ISelectionId,
reloadTooltipDataOnMouseMove?: boolean): void;
hide(): void;
}
ITooltipServiceWrapper.addTooltip
TypeScript
Example:
TypeScript
tooltipServiceWrapper.addTooltip<TooltipEnabledDataPoint>(element,
(eventArgs: TooltipEventArgs<TooltipEnabledDataPoint>) => {
return eventArgs.data.tooltipInfo;
});
ITooltipServiceWrapper.hide
TypeScript
hide(): void;
Example:
TypeScript
let tooltipServiceWrapper =
createTooltipServiceWrapper(options.host.tooltipService, options.element);
// options are from the VisualConstructorOptions.
tooltipServiceWrapper.hide();
Interfaces
Interfaces are used during TooltipServiceWrapper creation and when it's used. They
were mentioned in examples from previous articles here.
TooltipEventArgs
TypeScript
interface TooltipEventArgs<TData> {
data: TData;
coordinates: number[];
elementCoordinates: number[];
context: HTMLElement;
isTouchEvent: boolean;
}
TooltipEnabledDataPoint
TypeScript
interface TooltipEnabledDataPoint {
tooltipInfo?: powerbi.extensibility.VisualTooltipDataItem[];
}
TooltipServiceWrapperOptions
TypeScript
interface TooltipServiceWrapperOptions {
tooltipService: ITooltipService;
rootElement: Element;
handleTouchDelay: number;
Touch events
Now tooltip utils can handle several touch events that are useful for mobile
development.
touchStartEventName
TypeScript
touchEndEventName
TypeScript
usePointerEvents
TypeScript
This method returns the current touchStart event related to a pointer or not.
Feedback
Was this page helpful? Yes No
This article describes how to generate and install Secure Sockets Layer (SSL) certificates
for Power BI visuals.
For the Windows, macOS X, and Linux procedures, you must have the Power BI Visual
Tools pbiviz package installed. For more information, see Set up your environment for
developing a Power BI visual.
PowerShell
pbiviz --install-cert
For Windows 7, the pbiviz tool requires the OpenSSL utility to be available from the
command line. To install OpenSSL, go to OpenSSL or OpenSSL Binaries .
You can also install the OpenSSL utility by running either of the following commands:
By using MacPorts:
pbiviz --install-cert
Before you begin, run the following commands to make sure openssl and certutil are
installed:
sh
which openssl
which certutil
If openssl and certutil aren't installed, install the openssl and libnss3 utilities.
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment,
dataEncipherment
subjectAltName = @alt_names
[ alt_names ]
DNS.1=localhost
sh
touch $HOME/.rnd
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout
/tmp/local-root-ca.key -out /tmp/local-root-ca.pem -subj "/C=US/CN=Local
Root CA/O=Local Root CA"
openssl x509 -outform pem -in /tmp/local-root-ca.pem -out /tmp/local-root-
ca.crt
sh
PBIVIZ=`which pbiviz`
PBIVIZ=`dirname $PBIVIZ`
PBIVIZ="$PBIVIZ/../lib/node_modules/powerbi-visuals-tools/certs"
# Make sure that $PBIVIZ contains the correct certificate directory path. ls
$PBIVIZ should list 'blank' file.
openssl req -new -nodes -newkey rsa:2048 -keyout
$PBIVIZ/PowerBIVisualTest_private.key -out $PBIVIZ/PowerBIVisualTest.csr -
subj "/C=US/O=PowerBI Visuals/CN=localhost"
openssl x509 -req -sha256 -days 1024 -in $PBIVIZ/PowerBIVisualTest.csr -CA
/tmp/local-root-ca.pem -CAkey /tmp/local-root-ca.key -CAcreateserial -
extfile /tmp/openssl.cnf -out $PBIVIZ/PowerBIVisualTest_public.crt
sh
sh
sh
sh
sudo rm /usr/local/share/ca-certificates/local-root-ca.pem
sudo update-ca-certificates --fresh
You can usually find the PowerBI-visuals-tools web server certificates by running one
of the following commands:
%appdata%\npm\node_modules\PowerBI-visuals-tools\certs
PFX format
If you use the Personal Information Exchange (PFX) certificate format, save the certificate
file as PowerBIVisualTest_public.pfx.
\PowerBI-visuals-tools\config.json
"server":{
"root":"webRoot",
"assetsRoute":"/assets",
"privateKey":"certs/PowerBIVisualTest_private.key",
"certificate":"certs/PowerBIVisualTest_public.crt",
"pfx":"certs/PowerBIVisualTest_public.pfx",
"port":"8080",
"passphrase":"<YOUR PASSPHRASE>"
}
Related content
Develop a Power circle card BI visual
Power BI visuals samples
Publish a Power BI visual to AppSource
Feedback
Was this page helpful? Yes No