Incorporación de interactividad en un objeto visual mediante las selecciones de objetos visuales de Power BI
Power BI proporciona dos maneras de interactuar con objetos visuales: selección y filtrado. En el ejemplo siguiente, se muestra cómo seleccionar un elemento de un objeto visual y notificar a los demás objetos visuales del informe sobre el estado de selección nuevo.
La interfaz corresponde a un objeto Selection
:
export interface ISelectionId {
equals(other: ISelectionId): boolean;
includes(other: ISelectionId, ignoreHighlight?: boolean): boolean;
getKey(): string;
getSelector(): Selector;
getSelectorsByColumn(): SelectorsByColumn;
hasIdentity(): boolean;
}
Uso del administrador de selección para seleccionar puntos de datos
El host del objeto visual proporciona un método para crear una instancia del administrador de selección. El administrador de selección tiene un método correspondiente para cada una de las acciones siguientes:
- Seleccionar
- Borrar la selección
- Mostrar el menú contextual
- Almacenar las selecciones actuales
- Comprobar el estado de la selección
Creación de una instancia del administrador de selección
Para usar el administrador de selección, cree la instancia de un administrador de selección. Por lo general, los objetos visuales crean una instancia del administrador de selección en la sección constructor
del 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();
}
// ...
}
Creación de una instancia del generador de selección
Cuando se crea la instancia del administrador de selección, debe crear selections
para cada punto de datos del objeto visual. El método createSelectionIdBuilder
del objeto del host del objeto visual genera una selección para cada punto de datos. Este método devuelve una instancia del objeto con la interfaz 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;
}
Este objeto tiene métodos correspondientes para crear selections
para tipos diferentes de asignaciones de vistas de datos.
Nota
Los métodos withTable
y withMatrixNode
se introdujeron en la API 2.5.0 de los objetos visuales de Power BI.
Si necesita usar selecciones para las asignaciones de vistas de datos de tabla o matriz, actualice la API a la versión 2.5.0 o superior.
Creación de selecciones para la asignación de vistas de datos de categóricos
Revisemos cómo las selecciones representan el mapeo de vistas de datos categóricos para un modelo semántico de ejemplo:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Automóvil nacional | 28883 |
Chrysler | Camión nacional | 117131 |
Chrysler | Automóvil importado | 0 |
Chrysler | Camión importado | 6362 |
Ford | Automóvil nacional | 50032 |
Ford | Camión nacional | 122446 |
Ford | Automóvil importado | 0 |
Ford | Camión importado | 0 |
GM | Automóvil nacional | 65426 |
GM | Camión nacional | 138122 |
GM | Automóvil importado | 197 |
GM | Camión importado | 0 |
Honda | Automóvil nacional | 51450 |
Honda | Camión nacional | 46115 |
Honda | Automóvil importado | 2932 |
Honda | Camión importado | 0 |
Nissan | Automóvil nacional | 51476 |
Nissan | Camión nacional | 47343 |
Nissan | Automóvil importado | 5485 |
Nissan | Camión importado | 1430 |
Toyota | Automóvil nacional | 55643 |
Toyota | Camión nacional | 61227 |
Toyota | Automóvil importado | 20799 |
Toyota | Camión importado | 23614 |
El objeto visual utiliza la asignación de vistas de datos siguientes:
{
"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"
}
}
]
}
}
}
}
]
}
En el ejemplo anterior, Manufacturer
es columns
y Type
es rows
. Se crea una serie al agrupar valores por rows
(Type
).
El objeto visual debe poder segmentar los datos por Manufacturer
o Type
.
Por ejemplo, si un usuario selecciona Chrysler
por Manufacturer
, otros objetos visuales deberían mostrar los datos siguientes:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Automóvil nacional | 28883 |
Chrysler | Camión nacional | 117131 |
Chrysler | Automóvil importado | 0 |
Chrysler | Camión importado | 6362 |
Cuando el usuario selecciona Import Car
por Type
(selecciona datos por serie), los otros objetos visuales deberían mostrar estos datos:
Fabricante | Tipo | Valor |
---|---|---|
Chrysler | Automóvil importado | 0 |
Ford | Automóvil importado | 0 |
GM | Automóvil importado | 197 |
Honda | Automóvil importado | 2932 |
Nissan | Automóvil importado | 5485 |
Toyota | Automóvil importado | 20799 |
Para mostrar datos segmentados, rellene los cubos de datos del objeto visual como se indica a continuación:
En el ejemplo anterior, Manufacturer
es la categoría (columnas), Type
es la serie (filas) y Sales
es el valor (Values
) para la serie.
Nota
Se requieren Values
para mostrar una serie porque, según la asignación de vistas de datos, Values
se agrupan por los datos de Rows
.
Creación de selecciones para categorías
// 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);
}
En el código de ejemplo anterior, recorrimos en iteración todas las categorías. En cada iteración llamamos a createSelectionIdBuilder
para crear la selección siguiente para cada categoría llamando al método withCategory
del generador de selección. El método createSelectionId
se usa como método final para devolver el objeto selection
generado.
En el método withCategory
, pasamos la columna de category
; en el ejemplo es Manufacturer
y el índice del elemento de categoría.
Creación de selecciones para la serie
// 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);
});
Creación de selecciones para asignación de vistas de datos de tabla
En el ejemplo siguiente se muestra la asignación de vistas de datos de tabla:
{
"dataRoles": [
{
"displayName": "Values",
"name": "values",
"kind": "GroupingOrMeasure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
}
}
}
}
]
}
Para crear una selección para cada fila de la asignación de vistas de datos de tabla, llame al método withTable
del generador de selección.
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();
}
}
El código del objeto visual recorre en iteración las filas de la tabla y cada fila llama al método withTable
de tabla. Los parámetros del método withTable
son el objeto table
y el índice de la fila de la tabla.
Creación de selecciones para asignación de vistas de datos de 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);
});
}
}
}
En el ejemplo, nodeWalker
llama de manera recursiva a cada nodo y a los nodos secundarios.
nodeWalker
crea un objeto nodeSelection
en cada llamada. Cada nodeSelection
representa una selection
de los nodos correspondientes.
Selección de puntos de datos para segmentar otros objetos visuales
En este ejemplo, creamos un controlador de clics para los elementos de botón. El controlador llama al método select
del administrador de selección y pasa el objeto de selección.
button.addEventListener("click", () => {
// handle click event to apply correspond selection
this.selectionManager.select(categorySelectionId);
});
La interfaz del método select
es:
interface ISelectionManager {
// ...
select(selectionId: ISelectionId | ISelectionId[], multiSelect?: boolean): IPromise<ISelectionId[]>;
// ...
}
El método select
puede aceptar una matriz de selecciones. Esto permite que el objeto visual tenga varios puntos de datos seleccionados a la vez. El segundo parámetro, multiSelect
, es responsable de las selecciones múltiples. Si el valor de multiSelect
es verdadero, Power BI no borra el estado de la selección anterior cuando aplica la selección actual. Si el valor es falso, se sobrescribe la selección anterior.
Un ejemplo típico del uso de multiSelect
es controlar el estado del botón Ctrl mediante un evento de clic. Si mantiene presionado el botón Ctrl, puede seleccionar más de un objeto.
button.addEventListener("click", (mouseEvent) => {
const multiSelect = (mouseEvent as MouseEvent).ctrlKey;
this.selectionManager.select(seriesSelectionId, multiSelect);
});