Adicione interatividade ao visual pelas seleções de visuais do Power BI
O Power BI fornece duas maneiras de interagir com visuais: selecionar e filtrar. O exemplo a seguir demonstra como selecionar um item de um visual e notificar os outros visuais no relatório sobre o novo estado de seleção.
A interface corresponde a um objeto Selection
:
export interface ISelectionId {
equals(other: ISelectionId): boolean;
includes(other: ISelectionId, ignoreHighlight?: boolean): boolean;
getKey(): string;
getSelector(): Selector;
getSelectorsByColumn(): SelectorsByColumn;
hasIdentity(): boolean;
}
Usar o gerenciador de seleção para selecionar pontos de dados
O objeto de host do visual fornece um método para criar uma instância do gerenciador de seleção. O gerenciador de seleção tem um método correspondente para cada uma das seguintes ações:
- Selecionar
- Desmarcar a seleção
- Mostrar o menu de contexto
- Armazenar as seleções atuais
- Verificar o estado de seleção
Criar instância do gerenciador de seleção
Para usar o gerenciador de seleção, crie a instância do gerenciador de seleção. Geralmente, os visuais criam uma instância do gerenciador de seleção na seção constructor
do objeto visual.
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private selectionManager: ISelectionManager;
// ...
constructor(options: VisualConstructorOptions) {
this.host = options.host;
// ...
this.selectionManager = this.host.createSelectionManager();
}
// ...
}
Criar instância do construtor de seleção
Quando a instância do gerenciador de seleção é criada, você precisa criar selections
para cada ponto de dados do visual. O método createSelectionIdBuilder
do objeto de host visual gera uma seleção para cada ponto de dados. Esse método retorna uma instância do objeto com a interface powerbi.visuals.ISelectionIdBuilder
:
export interface ISelectionIdBuilder {
withCategory(categoryColumn: DataViewCategoryColumn, index: number): this;
withSeries(seriesColumn: DataViewValueColumns, valueColumn: DataViewValueColumn | DataViewValueColumnGroup): this;
withMeasure(measureId: string): this;
withMatrixNode(matrixNode: DataViewMatrixNode, levels: DataViewHierarchyLevel[]): this;
withTable(table: DataViewTable, rowIndex: number): this;
createSelectionId(): ISelectionId;
}
Esse objeto tem métodos correspondentes para criar selections
para diferentes tipos de mapeamentos de exibição de dados.
Observação
Os métodos withTable
e withMatrixNode
foram introduzidos na API 2.5.0 dos visuais do Power BI.
Se você precisar usar seleções para mapeamentos de exibição de dados de tabela ou matriz, atualize para a versão da API 2.5.0 ou superior.
Criar seleções para o mapeamento da exibição de dados categóricos
Vamos examinar como as seleções representam o mapeamento categórico de exibição de dados para um modelo semântico de exemplo:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Carro nacional | 28883 |
Chrysler | Caminhonete nacional | 117131 |
Chrysler | Carro importado | 0 |
Chrysler | Caminhonete importada | 6362 |
Ford | Carro nacional | 50032 |
Ford | Caminhonete nacional | 122446 |
Ford | Carro importado | 0 |
Ford | Caminhonete importada | 0 |
GM | Carro nacional | 65426 |
GM | Caminhonete nacional | 138122 |
GM | Carro importado | 197 |
GM | Caminhonete importada | 0 |
Honda | Carro nacional | 51450 |
Honda | Caminhonete nacional | 46115 |
Honda | Carro importado | 2932 |
Honda | Caminhonete importada | 0 |
Nissan | Carro nacional | 51476 |
Nissan | Caminhonete nacional | 47343 |
Nissan | Carro importado | 5485 |
Nissan | Caminhonete importada | 1430 |
Toyota | Carro nacional | 55643 |
Toyota | Caminhonete nacional | 61227 |
Toyota | Carro importado | 20799 |
Toyota | Caminhonete importada | 23614 |
O elemento visual usa o seguinte mapeamento de exibição de dados:
{
"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"
}
}
]
}
}
}
}
]
}
No exemplo anterior, Manufacturer
é columns
e Type
é rows
. Uma série é criada agrupando valores por rows
(Type
).
O visual deve ser capaz de segmentar dados por Manufacturer
ou Type
.
Por exemplo, quando o usuário seleciona Chrysler
por Manufacturer
, outros elementos visuais devem mostrar os seguintes dados:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Carro nacional | 28883 |
Chrysler | Caminhonete nacional | 117131 |
Chrysler | Carro importado | 0 |
Chrysler | Caminhonete importada | 6362 |
Quando o usuário seleciona Import Car
por Type
(seleciona dados por série), os outros elementos visuais devem mostrar os seguintes dados:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Carro importado | 0 |
Ford | Carro importado | 0 |
GM | Carro importado | 197 |
Honda | Carro importado | 2932 |
Nissan | Carro importado | 5485 |
Toyota | Carro importado | 20799 |
Para exibir dados divididos, preencha as cestas de dados do visual da seguinte maneira:
No exemplo anterior, Manufacturer
é categoria (colunas), Type
é série (linhas) e Sales
é Values
para série.
Observação
Os Values
são necessários para exibir uma série porque, de acordo com o mapeamento de exibição de dados, os Values
são agrupados por dados de Rows
.
Criar seleções para categorias
// categories
const categories = dataView.categorical.categories;
// create label for 'Manufacturer' column
const p = document.createElement("p") as HTMLParagraphElement;
p.innerText = categories[0].source.displayName.toString();
this.target.appendChild(p);
// get count of category elements
const categoriesCount = categories[0].values.length;
// iterate all categories to generate selection and create button elements to use selections
for (let categoryIndex = 0; categoryIndex < categoriesCount; categoryIndex++) {
const categoryValue: powerbi.PrimitiveValue = categories[0].values[categoryIndex];
const categorySelectionId = this.host.createSelectionIdBuilder()
.withCategory(categories[0], categoryIndex) // we have only one category (only one `Manufacturer` column)
.createSelectionId();
this.dataPoints.push({
value: categoryValue,
selection: categorySelectionId
});
console.log(categorySelectionId);
// create button element to apply selection on click
const button = document.createElement("button") as HTMLButtonElement;
button.value = categoryValue.toString();
button.innerText = categoryValue.toString();
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
this.target.appendChild(button);
}
No código de exemplo anterior, iteramos por todas as categorias. Em cada iteração, chamamos createSelectionIdBuilder
para criar a próxima seleção para cada categoria chamando o método withCategory
do construtor de seleção. O método createSelectionId
é usado como um método final para retornar o objeto selection
gerado.
No método withCategory
, passamos a coluna de category
, no exemplo, é Manufacturer
e o índice do elemento da categoria.
Criar seleções para séries
// get groupped values for series
const series: powerbi.DataViewValueColumnGroup[] = dataView.categorical.values.grouped();
// create label for 'Type' column
const p2 = document.createElement("p") as HTMLParagraphElement;
p2.innerText = dataView.categorical.values.source.displayName;
this.target.appendChild(p2);
// iterate all series to generate selection and create button elements to use selections
series.forEach( (ser: powerbi.DataViewValueColumnGroup) => {
// create selection id for series
const seriesSelectionId = this.host.createSelectionIdBuilder()
.withSeries(dataView.categorical.values, ser)
.createSelectionId();
this.dataPoints.push({
value: ser.name,
selection: seriesSelectionId
});
// create button element to apply selection on click
const button = document.createElement("button") as HTMLButtonElement;
button.value =ser.name.toString();
button.innerText = ser.name.toString();
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(seriesSelectionId);
});
this.target.appendChild(button);
});
Criar seleções para o mapeamento da exibição de dados da tabela
O seguinte exemplo mostra o mapeamento de exibição de dados de tabela:
{
"dataRoles": [
{
"displayName": "Values",
"name": "values",
"kind": "GroupingOrMeasure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
}
}
}
}
]
}
Para criar uma seleção para cada linha do mapeamento da visualização de dados da tabela, chame o método withTable
do construtor da seleção.
public update(options: VisualUpdateOptions) {
const dataView = options.dataViews[0];
dataView.table.rows.forEach((row: DataViewTableRow, rowIndex: number) => {
this.target.appendChild(rowDiv);
const selection: ISelectionId = this.host.createSelectionIdBuilder()
.withTable(dataView.table, rowIndex)
.createSelectionId();
}
}
O código do visual itera as linhas da tabela e cada linha chama o método de tabela withTable
. Os parâmetros do método withTable
são o objeto e table
e o índice da linha da tabela.
Criar seleções para o mapeamento da exibição de dados da matriz
public update(options: VisualUpdateOptions) {
const host = this.host;
const rowLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;
const columnLevels: powerbi.DataViewHierarchyLevel[] = dataView.matrix.rows.levels;
// iterate rows hierarchy
nodeWalker(dataView.matrix.rows.root, rowLevels);
// iterate columns hierarchy
nodeWalker(dataView.matrix.columns.root, columnLevels);
function nodeWalker(node: powerbi.DataViewMatrixNode, levels: powerbi.DataViewHierarchyLevel[]) {
const nodeSelection = host.createSelectionIdBuilder().withMatrixNode(node, levels);
if (node.children && node.children.length) {
node.children.forEach(child => {
nodeWalker(child, levels);
});
}
}
}
Na amostra, nodeWalker
chama recursivamente cada nó e cada nó filho.
O nodeWalker
cria um objeto nodeSelection
em cada chamada. Cada nodeSelection
um representa um selection
dos nós correspondentes.
Selecionar pontos de dados para segmentar outros visuais
Neste exemplo, criamos um manipulador de cliques para elementos de botão. O manipulador chama o método select
do gerenciador de seleção e passa o objeto de seleção.
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
A interface do método select
:
interface ISelectionManager {
// ...
select(selectionId: ISelectionId | ISelectionId[], multiSelect?: boolean): IPromise<ISelectionId[]>;
// ...
}
O método select
pode aceitar uma variedade de seleções. Isso permite que o visual tenha vários pontos de dados selecionados ao mesmo tempo. O segundo parâmetro, multiSelect
, é responsável pela seleção múltipla. Se multiSelect
for verdadeiro, o Power BI não limpará o estado de seleção anterior ao aplicar a seleção atual. Se o valor for falso, a seleção anterior será substituída.
Um exemplo típico do uso de multiSelect
é lidar com o estado do botão Ctrl em um evento de clique. Quando o botão Ctrl é pressionado, você pode selecionar mais de um objeto.
button.addEventListener("click", (mouseEvent) => {
const multiSelect = (mouseEvent as MouseEvent).ctrlKey;
this.selectionManager.select(seriesSelectionId, multiSelect);
});