Lägga till interaktivitet i visuella objekt av visuella Power BI-objekt

Power BI tillhandahåller två sätt att interagera med visuella objekt – att välja och filtrera. I följande exempel visas hur du väljer ett objekt från ett visuellt objekt och meddelar de andra visuella objekten i rapporten om det nya urvalstillståndet.

Gränssnittet motsvarar ett Selection objekt:

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

Använd markeringshanteraren för att välja datapunkter

Det visuella värdobjektet innehåller en metod för att skapa en instans av markeringshanteraren. Urvalshanteraren har en motsvarande metod för var och en av följande åtgärder:

  • Välj
  • Rensa markeringen
  • Visa snabbmenyn
  • Lagra de aktuella valen
  • Kontrollera markeringstillståndet

Skapa en instans av markeringshanteraren

Om du vill använda markeringshanteraren skapar du instansen av en markeringshanterare. Vanligtvis skapar visuella objekt en instans av markeringshanteraren i constructor avsnittet i det visuella objektet.

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

Skapa en instans av markeringsverktyget

När urvalshanterarens instans skapas måste du skapa selections för varje datapunkt i det visuella objektet. Metoden för det visuella värdobjektet createSelectionIdBuilder genererar en markering för varje datapunkt. Den här metoden returnerar en instans av objektet med gränssnittet 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;
}

Det här objektet har motsvarande metoder för att skapa selections för olika typer av datavymappningar.

Kommentar

Metoderna withTable och withMatrixNode introducerades i API 2.5.0 för visuella Power BI-objekt. Om du behöver använda val för tabell- eller matrisdatavymappningar uppdaterar du till API-version 2.5.0 eller senare.

Skapa val för kategorisk datavymappning

Nu ska vi gå igenom hur val representerar kategorisk datavymappning för en exempelsemantisk modell:

Tillverkare Type Värde
Chrysler Inrikesbil 28883
Chrysler Inrikes lastbil 117131
Chrysler Importera bil 0
Chrysler Importera lastbil 6362
Ford Inrikesbil 50032
Ford Inrikes lastbil 122446
Ford Importera bil 0
Ford Importera lastbil 0
GM Inrikesbil 65426
GM Inrikes lastbil 138122
GM Importera bil 197
GM Importera lastbil 0
Honda Inrikesbil 51450
Honda Inrikes lastbil 46115
Honda Importera bil 2932
Honda Importera lastbil 0
Nissan Inrikesbil 51476
Nissan Inrikes lastbil 47343
Nissan Importera bil 5485
Nissan Importera lastbil 1430
Toyota Inrikesbil 55643
Toyota Inrikes lastbil 61227
Toyota Importera bil 20799
Toyota Importera lastbil 23614

Det visuella objektet använder följande datavymappning:

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

I föregående exempel Manufacturer är columns och Type är rows. En serie skapas genom att värden grupperas efter rows (Type).

Det visuella objektet ska kunna segmentera data efter Manufacturer eller Type.

Om en användare till exempel väljer Chrysler efter Manufacturerbör andra visuella objekt visa följande data:

Tillverkare Type Värde
Chrysler Inrikesbil 28883
Chrysler Inrikes lastbil 117131
Chrysler Importera bil 0
Chrysler Importera lastbil 6362

När användaren väljer efter Import CarType (väljer data efter serie) bör de andra visuella objekten visa följande data:

Tillverkare Type Värde
Chrysler Importera bil 0
Ford Importera bil 0
GM Importera bil 197
Honda Importera bil 2932
Nissan Importera bil 5485
Toyota Importera bil 20799

Screenshot that shows the visual with selections.

Om du vill visa utsnittsdata fyller du det visuella objektets datakorgar på följande sätt:

Screenshot that shows visual's data baskets.

I föregående exempel Manufacturer är kategori (kolumner), Type är serie (rader) och Sales är Values för serier.

Kommentar

Values krävs för att visa en serie eftersom, enligt datavymappningen, Values grupperas efter Rows data.

Skapa val för kategorier

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

I föregående exempelkod itererar vi igenom alla kategorier. I varje iteration anropar createSelectionIdBuilder vi för att skapa nästa val för varje kategori genom att anropa withCategory metoden för markeringsverktyget. Metoden createSelectionId används som en slutlig metod för att returnera det genererade selection objektet.

withCategory I -metoden skickar vi kolumnen categoryi , i exemplet, dess Manufactureroch indexet för kategorielementet.

Skapa val för serier

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

Skapa val för mappning av tabelldatavyer

I följande exempel visas mappning av tabelldatavyer:

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

Om du vill skapa en markering för varje rad med mappning av tabelldatavyer anropar withTable du metoden för markeringsverktyget.

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

Den visuella koden itererar raderna i tabellen och varje rad anropar withTable tabellmetoden. Parametrar för withTable metoden är table objektet och indexet för tabellraden.

Skapa val för mappning av matrisdatavyer

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

I exemplet nodeWalker anropar rekursivt varje nod och underordnad nod.

nodeWalker skapar ett nodeSelection objekt för varje anrop. Var och nodeSelection en representerar en selection av motsvarande noder.

Välj datapunkter för att segmentera andra visuella objekt

I det här exemplet skapade vi en klickhanterare för knappelement. Hanteraren anropar select markeringshanterarens metod och skickar markeringsobjektet.

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

Metodens select gränssnitt:

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

Metoden select kan acceptera en matris med val. På så sätt kan ditt visuella objekt ha flera datapunkter markerade samtidigt. Den andra parametern, multiSelect, ansvarar för flera val. Om multiSelect är sant rensar Power BI inte det tidigare markeringstillståndet när den aktuella markeringen tillämpas. Om värdet är falskt skrivs den tidigare markeringen över.

Ett vanligt exempel på hur du använder multiSelect är att hantera Ctrl-knapptillståndet för en klickhändelse. När Ctrl-knappen hålls nere kan du välja fler än ett objekt.

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