Aggiungere interattività negli oggetti visivi tramite le selezioni degli oggetti visivi di Power BI

Power BI offre due modi per interagire con gli oggetti visivi, ovvero la selezione e il filtro. Nell'esempio seguente viene illustrato come selezionare un elemento da un oggetto visivo e notificare agli altri oggetti visivi nel report lo stato di nuova selezione.

L'interfaccia corrisponde a un oggetto Selection:

export interface ISelectionId {
    equals(other: ISelectionId): boolean;
    includes(other: ISelectionId, ignoreHighlight?: boolean): boolean;
    getKey(): string;
    getSelector(): Selector;
    getSelectorsByColumn(): SelectorsByColumn;
    hasIdentity(): boolean;
}

Come usare la gestione selezione per selezionare i punti dati

L'oggetto host dell'oggetto visivo fornisce un metodo per la creazione di un'istanza di gestione selezione. La gestione selezione dispone di un metodo corrispondente per ognuna delle azioni seguenti:

  • Seleziona
  • Cancellare la selezione
  • Mostrare il menu di scelta rapida
  • Archiviare le selezioni correnti
  • Controllare lo stato selezione

Creare un'istanza della gestione selezione

Per usare la gestione selezione, creare la relativa istanza. Gli oggetti visivi creano in genere un'istanza di gestione selezione nella sezione constructor dell'oggetto visivo.

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();
    }
    // ...
}

Creare un'istanza del generatore di selezione

Quando viene creata l'istanza di gestione selezione, è necessario creare selections per ogni punto dati dell'oggetto visivo. Il metodo createSelectionIdBuilder dell'oggetto host visivo genera una selezione per ciascun punto dati. Questo metodo restituisce un'istanza dell'oggetto con l'interfaccia 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;
}

Questo oggetto ha metodi corrispondenti per creare selections per diversi tipi di mapping di visualizzazione dati.

Nota

I metodi withTable e withMatrixNode sono stati introdotti nell'API 2.5.0 degli oggetti visivi di Power BI. Se è necessario usare le selezioni per i mapping di visualizzazione dati di tabella o di matrice, aggiornare l'API alla versione 2.5.0 o successiva.

Creare selezioni per il mapping di visualizzazione dati categorica

Si esaminerà ora come le selezioni rappresentano il mapping delle visualizzazioni dei dati categoriche per un modello semantico di esempio:

Produttore Type Valore
Chrysler Domestic Car 28883
Chrysler Domestic Truck 117131
Chrysler Import Car 0
Chrysler Import Truck 6362
Ford Domestic Car 50032
Ford Domestic Truck 122446
Ford Import Car 0
Ford Import Truck 0
GM Domestic Car 65426
GM Domestic Truck 138122
GM Import Car 197
GM Import Truck 0
Honda Domestic Car 51450
Honda Domestic Truck 46115
Honda Import Car 2932
Honda Import Truck 0
Nissan Domestic Car 51476
Nissan Domestic Truck 47343
Nissan Import Car 5485
Nissan Import Truck 1430
Toyota Domestic Car 55643
Toyota Domestic Truck 61227
Toyota Import Car 20799
Toyota Import Truck 23614

L'oggetto visivo usa il mapping di visualizzazione dati seguente:

{
    "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"
                                }
                            }
                        ]
                    }
                }
            }
        }
    ]
}

Nell'esempio precedente Manufacturer è columns e Type è rows. Viene creata una serie da valori di raggruppamento per rows (Type).

L'oggetto visivo deve essere in grado di suddividere i dati in base a Manufacturer o Type.

Ad esempio, se un utente seleziona Chrysler per Manufacturer, gli altri oggetti visivi devono mostrare i dati seguenti:

Produttore Type Valore
Chrysler Domestic Car 28883
Chrysler Domestic Truck 117131
Chrysler Import Car 0
Chrysler Import Truck 6362

Quando l'utente seleziona Import Car per Type (seleziona i dati in base alla serie), gli altri oggetti visivi visualizzano i dati seguenti:

Produttore Type Valore
Chrysler Import Car 0
Ford Import Car 0
GM Import Car 197
Honda Import Car 2932
Nissan Import Car 5485
Toyota Import Car 20799

Screenshot che mostra l'oggetto visivo con le selezioni.

Per visualizzare i dati sezionati, compilare le tabelle di dati dell'oggetto visivo come indicato di seguito:

Screenshot che mostra le tabelle dati dell'oggetto visivo.

Nell'esempio precedente, Manufacturer è una categoria (colonne), Type è una serie (righe) e Sales è Values per la serie.

Nota

Values sono necessari per la visualizzazione di una serie perché, in base al mapping della vista dati, Values sono raggruppati per dati Rows.

Creare selezioni per le categorie

// 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);
}

Nel codice di esempio precedente, viene eseguita l'iterazione di tutte le categorie. In ogni iterazione, si chiama createSelectionIdBuilder per creare la selezione successiva per ogni categoria chiamando il metodo withCategory del generatore di selezione. Il metodo createSelectionId viene usato come metodo finale per restituire l'oggetto selection generato.

Nel metodo withCategory, viene passata la colonna di category, nell'esempio si tratta di Manufacturer e dell'indice dell'elemento categoria.

Creare selezioni per le 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);
});

Creare selezioni per il mapping di visualizzazione dati di tabella

L'esempio seguente mostra il mapping della visualizzazione dei dati della tabella:

{
    "dataRoles": [
        {
            "displayName": "Values",
            "name": "values",
            "kind": "GroupingOrMeasure"
        }
    ],
    "dataViewMappings": [
        {
            "table": {
                "rows": {
                    "for": {
                        "in": "values"
                    }
                }
            }
        }
    ]
}

Per creare una selezione per ogni riga del mapping di visualizzazione dei dati della tabella, chiamare il metodo withTable del generatore di selezione.

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();
    }
}

Il codice visivo esegue l'iterazione delle righe della tabella e ogni riga chiama il metodo tabella withTable. I parametri del metodo withTable sono l'oggetto table e l'indice della riga della tabella.

Creare selezioni per il mapping di visualizzazione dati di matrice

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);
            });
        }
    }
}

Nell'esempio, nodeWalker esegue chiamate in modo ricorsivo per ogni nodo e nodo figlio.

nodeWalker crea un oggetto nodeSelection a ogni chiamata. Ogni nodeSelection rappresenta un selection di nodi corrispondenti.

Selezionare i punti dati per suddividere altri oggetti visivi

In questo esempio, è stato creato un gestore di clic per gli elementi del pulsante. Il gestore chiama il metodo select di gestione selezione e passa l'oggetto di selezione.

button.addEventListener("click", () => {
    // handle click event to apply correspond selection
    this.selectionManager.select(categorySelectionId);
});

L'interfaccia del metodo select:

interface ISelectionManager {
    // ...
    select(selectionId: ISelectionId | ISelectionId[], multiSelect?: boolean): IPromise<ISelectionId[]>;
    // ...
}

Il metodo select può accettare una matrice di selezioni. Ciò consente all'oggetto visivo di disporre di più punti dati contemporaneamente. Il secondo parametro, multiSelect, è responsabile della selezione multipla. Se multiSelect è True, Power BI non cancella lo stato di selezione precedente quando applica la selezione corrente. Se il valore è False, la selezione precedente viene sovrascritta.

Un esempio tipico dell'uso di multiSelect consiste nel gestire lo stato del pulsante CTRL in un evento clic. Quando si tiene premuto il pulsante CTRL, è possibile selezionare più di un oggetto.

button.addEventListener("click", (mouseEvent) => {
    const multiSelect = (mouseEvent as MouseEvent).ctrlKey;
    this.selectionManager.select(seriesSelectionId, multiSelect);
});