Para dar suporte às ações de drill down no seu visual, adicione um novo campo a capabilities.json chamado drill-down. Esse campo tem uma propriedade chamada roles que contém o nome do dataRole no qual você deseja habilitar as ações de detalhamento.
"drilldown": {
"roles": [
"category"
]
}
Observação
A função dataRole de drill-down deve ser do tipo Grouping.
A propriedade max nas condições de dataRole deve ser definida como 1.
Depois de adicionar a função ao campo fazer drill down, os usuários podem arrastar vários campos para a função de dados.
Para criar um visual com suporte para drill-down, execute o comando a seguir:
pbiviz new testDrillDown -t default
Para criar um visual de amostra padrão, aplique a amostra de capabilities.json acima ao visual recém-criado.
Crie a propriedade para o contêiner div para armazenar elementos HTML do visual:
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// imports
export class Visual implements IVisual {
// visual properties
// ...
private div: HTMLDivElement; // <== NEW PROPERTY
constructor(options: VisualConstructorOptions) {
// constructor body
// ...
}
public update(options: VisualUpdateOptions) {
// update method 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);
}
}
Inclua todas as colunas de categoria (H1, H2, H3) para a nova hierarquia:
Após essas etapas, você deve obter o seguinte visual:
Adicionar menu de contexto aos elementos do visual
Para adicionar um menu de contexto aos botões no visual:
Salve o objeto host nas propriedades do visual e chame o método createSelectionManager para o gerenciador de seleção de criação para exibir um menu de contexto usando a API de Visuais do Power BI.
"use strict";
import "core-js/stable";
import "./../style/visual.less";
// default imports
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import ISelectionManager = powerbi.extensibility.ISelectionManager;
import ISelectionId = powerbi.visuals.ISelectionId;
export class Visual implements IVisual {
// visual properties
// ...
private div: HTMLDivElement;
private host: IVisualHost; // <== NEW PROPERTY
private selectionManager: ISelectionManager; // <== NEW PROPERTY
constructor(options: VisualConstructorOptions) {
// constructor body
// save the host in the visuals properties
this.host = options.host;
// create selection manager
this.selectionManager = this.host.createSelectionManager();
// ...
}
public update(options: VisualUpdateOptions) {
// update method body
// ...
}
// ...
}
Altere o corpo do retorno de chamada da função forEach para:
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();
let button = document.createElement("button");
button.innerText = category.toString();
// add event listener to click event
button.addEventListener("click", (event) => {
// call select method in the selection manager
this.selectionManager.select(selectionID);
});
button.addEventListener("contextmenu", (event) => {
// call showContextMenu method to display context menu on the visual
this.selectionManager.showContextMenu(selectionID, {
x: event.clientX,
y: event.clientY
});
event.preventDefault();
});
this.div.appendChild(button);
});
Aplicar os dados ao visual:
Na etapa final, você deve obter o visual com seleções e o menu de contexto:
Adicionar suporte de drill-down para mapeamento de exibição de dados de matriz
Para testar o visual com mapeamentos de exibição de dados de matriz, primeiro prepare os dados de amostra:
Linha 1
Linha 2
Linha 3
Coluna 1
Coluna 2
Coluna 3
Valores
R1
R11
R111
C1
C11
C111
1
R1
R11
R112
C1
C11
C112
2
R1
R11
R113
C1
C11
C113
3
R1
R12
R121
C1
C12
C121
4
R1
R12
R122
C1
C12
C122
5
R1
R12
R123
C1
C12
C123
6
R1
R13
R131
C1
C13
C131
7
R1
R13
R132
C1
C13
C132
8
R1
R13
R133
C1
C13
C133
9
R2
R21
R211
C2
C21
C211
10
R2
R21
R212
C2
C21
C212
11
R2
R21
R213
C2
C21
C213
12
R2
R22
R221
C2
C22
C221
13
R2
R22
R222
C2
C22
C222
14
R2
R22
R223
C2
C22
C223
16
R2
R23
R231
C2
C23
C231
17
R2
R23
R232
C2
C23
C232
18
R2
R23
R233
C2
C23
C233
19
Em seguida, aplique o seguinte mapeamento de exibição de dados ao visual:
Crie duas propriedades para duas divs de elementos de linhas e colunas:
export class Visual implements IVisual {
// ...
private rowsDiv: HTMLDivElement;
private colsDiv: HTMLDivElement;
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
// ...
// Create div elements and append to main div of the visual
this.rowsDiv = document.createElement("div");
this.target.appendChild(this.rowsDiv);
this.colsDiv = document.createElement("div");
this.target.appendChild(this.colsDiv);
}
// ...
}
Verifique os dados antes de renderizar os elementos e exiba o nível atual da hierarquia:
export class Visual implements IVisual {
// ...
constructor(options: VisualConstructorOptions) {
// constructor body
}
public update(options: VisualUpdateOptions) {
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
console.log('Visual update', options);
const dataView: DataView = options.dataViews[0];
const matrixDataView: DataViewMatrix = dataView.matrix;
// if the visual doesn't receive the data no reason to continue rendering
if (!matrixDataView ||
!matrixDataView.columns ||
!matrixDataView.rows ) {
return
}
// to display current level of hierarchy
if (typeof this.textNode !== undefined) {
this.textNode.textContent = categoricalDataView.categories[categoricalDataView.categories.length - 1].source.displayName.toString();
}
// ...
}
// ...
}
Crie a função treeWalker para percorrer a hierarquia:
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// generate selectionID for each node of matrix
const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withMatrixNode(matrixNode, levels)
.createSelectionId();
// ...
if (matrixNode.children) {
// create div element for level
const childDiv = document.createElement("div");
// add to current div
div.appendChild(childDiv);
// create paragraph element to display next
const p = document.createElement("p");
// display level name on paragraph element
const level = levels[matrixNode.level];
p.innerText = level.sources[level.sources.length - 1].displayName;
// add paragraph element to created child div
childDiv.appendChild(p);
// traversing child nodes
matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
}
}
Crie buttons para interagir com o visual e exibir o menu de contexto para pontos de extremidade de matriz:
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// generate selectionID for each node of matrix
const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
.withMatrixNode(matrixNode, levels)
.createSelectionId();
// create button element
let button = document.createElement("button");
// display node value/name of the button's text
button.innerText = matrixNode.value.toString();
// add event listener on click
button.addEventListener("click", (event) => {
// call select method in the selection manager
this.selectionManager.select(selectionID);
});
// display context menu on click
button.addEventListener("contextmenu", (event) => {
// call showContextMenu method to display context menu on the visual
this.selectionManager.showContextMenu(selectionID, {
x: event.clientX,
y: event.clientY
});
event.preventDefault();
});
div.appendChild(button);
if (matrixNode.children) {
// ...
}
}
Desmarque elementos div antes de renderizar os elementos novamente:
public update(options: VisualUpdateOptions) {
// ...
const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement) => {
// ...
}
// remove old elements
// to better performance use D3js pattern:
// https://d3js.org/#enter-exit
while (this.rowsDiv.firstChild) {
this.rowsDiv.removeChild(this.rowsDiv.firstChild);
}
// create label for row elements
const prow = document.createElement("p");
prow.innerText = "Rows";
this.rowsDiv.appendChild(prow);
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);
// render elements for rows
const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
rowRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.rows.levels, this.rowsDiv));
// render elements for columns
const colRoot = matrixDataView.columns.root;
colRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.columns.levels, this.colsDiv));
}
Finalmente, você deverá obter um visual com o menu de contexto:
Saiba como adicionar suporte a indicadores aos seus visuais personalizados no Power BI para que você possa alternar entre diferentes estados com indicadores.
Neste módulo, você vai adicionar medidas a um modelo de dados do Power BI pela primeira vez. Você vai usar hierarquias, visuais de matriz e DAX no modelo de dados para explorar ainda mais os dados.
Demonstre métodos e boas práticas que se alinhem aos requisitos técnicos e comerciais para modelagem, visualização e análise de dados com o Microsoft Power BI.