เพิ่มการโต้ตอบลงในภาพด้วยการเลือกภาพ Power BIAdd interactivity into visual by Power BI visuals selections

Power BI มีสองวิธีในการโต้ตอบระหว่างภาพคือ - การเลือกและการกรองPower BI provides two ways of interaction between visuals - selection and filtering. ตัวอย่างด้านล่างแสดงให้เห็นถึงวิธีการเลือกรายการใดๆ ในภาพเดียวและแจ้งภาพอื่นๆ ในรายงานเกี่ยวกับสถานะการเลือกใหม่The sample below demonstrates how to select any items in one visual and notify other visuals in the report about new selection state.

Selection ออบเจ็กต์ที่สอดคล้องกับอินเตอร์เฟซ:Selection object corresponds to the interface:

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

วิธีใช้ SelectionManager เพื่อเลือกจุดข้อมูลHow to use SelectionManager to select data points

ออบเจ็กต์โฮสต์วิชวลให้เมธอดในการสร้างอินสแตนซ์ของเครื่องมือจัดการการเลือกThe visual host object provides the method for creating an instance of selection manager. ตัวจัดการการเลือกที่รับผิดชอบในการเลือก ล้างการเลือก แสดงเมนูบริบท จัดเก็บการเลือกปัจจุบันและตรวจสอบสถานะการเลือกThe selection manager responsible to select, to clear selection, to show the context menu, to store current selections and check selection state. และตัวจัดการการเลือกมีเมธอดที่สอดคล้องกันสำหรับการดำเนินการดังกล่าวAnd the selection manager has corresponded methods for those actions.

สร้างอินสแตนซ์ของตัวจัดการการเลือกCreate an instance of the selection manager

สำหรับการใช้ตัวจัดการการเลือก คุณจะต้องสร้างอินสแตนซ์ของตัวจัดการการเลือกFor using the selection manager, you need to create the instance of a selection manager. โดยทั่วไป วิชวลจะสร้างอินสแตนซ์ตัวจัดการการเลือกใน constructor ของออบเจ็กต์ของวิชวลUsually, visuals create a selection manager instance in the constructor of the visual object.

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

สร้างอินสแตนซ์ของตัวสร้างการเลือกCreate an instance of the selection builder

เมื่อมีการสร้างอินสแตนซ์ตัวจัดการการเลือก คุณจะต้องสร้าง selections สำหรับแต่ละจุดข้อมูลของภาพWhen the selection manager instance is created, you need to create selections for each data point of the visual. วัตถุโฮสต์ภาพมีวิธีการ createSelectionIdBuilder ในการสร้างการเลือกสำหรับแต่ละจุดข้อมูลThe visual host object provides createSelectionIdBuilder method to generate selection for each data point. เมธอดนี้ส่งกลับอินสแตนซ์ของออบเจ็กต์ที่มีอินเทอร์เฟซ powerbi.visuals.ISelectionIdBuilder:This method return instance of the object with 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;
}

ออบเจ็กต์นี้มีเมธอดที่สอดคล้องเพื่อสร้าง selections สำหรับการแมปมุมมองข้อมูลชนิดต่างๆThis object has corresponded methods to create selections for different types of data view mappings.

หมายเหตุ

มีการนำเมธอด withTable และ withMatrixNode มาใช้ใน API 2.5.0 ของวิชวล Power BIThe methods withTable and withMatrixNode were introduced on API 2.5.0 of the Power BI visuals. ถ้าคุณจำเป็นต้องใช้ตัวเลือกสำหรับการแมปมุมมองข้อมูลแบบตารางหรือเมทริกซ์ คุณจำเป็นต้องอัปเดต API ไปเป็นเวอร์ชัน 2.5.0 หรือใหม่กว่าIf you need to use selections for table or matrix data view mappings you need to update API version to 2.5.0 or higher.

สร้างการเลือกสำหรับการแมปมุมมองข้อมูลประเภทCreate selections for categorical data view mapping

มาดูกันว่าการเลือกจะแสดงถึงการแมปมุมมองข้อมูลแบบจัดกลุ่มสำหรับชุดข้อมูลตัวอย่างได้อย่างไร:Let's review how selections represent on categorical data view mapping for sample dataset:

ผู้ผลิตManufacturer ชนิดType ค่าValue
ไครสเลอร์Chrysler รถภายในประเทศDomestic Car 2888328883
ไครสเลอร์Chrysler รถบรรทุกภายในประเทศDomestic Truck 117131117131
ไครสเลอร์Chrysler รถนำเข้าImport Car 00
ไครสเลอร์Chrysler รถบรรทุกนำเข้าImport Truck 63626362
ฟอร์ดFord รถภายในประเทศDomestic Car 5003250032
ฟอร์ดFord รถบรรทุกภายในประเทศDomestic Truck 122446122446
ฟอร์ดFord รถนำเข้าImport Car 00
ฟอร์ดFord รถบรรทุกนำเข้าImport Truck 00
GMGM รถภายในประเทศDomestic Car 6542665426
GMGM รถบรรทุกภายในประเทศDomestic Truck 138122138122
GMGM รถนำเข้าImport Car 197197
GMGM รถบรรทุกนำเข้าImport Truck 00
ฮอนด้าHonda รถภายในประเทศDomestic Car 5145051450
ฮอนด้าHonda รถบรรทุกภายในประเทศDomestic Truck 4611546115
ฮอนด้าHonda รถนำเข้าImport Car 29322932
ฮอนด้าHonda รถบรรทุกนำเข้าImport Truck 00
นิสสันNissan รถภายในประเทศDomestic Car 5147651476
นิสสันNissan รถบรรทุกภายในประเทศDomestic Truck 4734347343
นิสสันNissan รถนำเข้าImport Car 54855485
นิสสันNissan รถบรรทุกนำเข้าImport Truck 14301430
โตโยต้าToyota รถภายในประเทศDomestic Car 5564355643
โตโยต้าToyota รถบรรทุกภายในประเทศDomestic Truck 6122761227
โตโยต้าToyota รถนำเข้าImport Car 2079920799
โตโยต้าToyota รถบรรทุกนำเข้าImport Truck 2361423614

และวิชวลใช้การแมปมุมมองข้อมูลต่อไปนี้:And the visual uses the following data view mapping:

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

ในตัวอย่าง Manufacturerคือ columns และ Type คือ rowsIn the sample, Manufacturer is columns and Type is rows. มีชุดข้อมูลที่สร้างขึ้นโดยการจัดกลุ่มค่าโดย rows (Type)There's series created by groupings values by rows (Type).

และการแสดงผลด้วยภาพควรสามารถแบ่งข้อมูลด้วย Manufacturer และ Type ด้วยAnd visual should able to slice data by Manufacturer and Type too.

ตัวอย่างเช่น เมื่อผู้ใช้เลือก Chrysler โดย Manufacturer ภาพอื่นๆ ควรแสดงข้อมูลต่อไปนี้:For example, when user selects Chrysler by Manufacturer, other visuals should show following data:

ผู้ผลิตManufacturer ชนิดType ค่าValue
ไครสเลอร์Chrysler รถภายในประเทศDomestic Car 2888328883
ไครสเลอร์Chrysler รถบรรทุกภายในประเทศDomestic Truck 117131117131
ไครสเลอร์Chrysler รถนำเข้าImport Car 00
ไครสเลอร์Chrysler รถบรรทุกนำเข้าImport Truck 63626362

เมื่อผู้ใช้เลือกImport CarโดยType (เลือกข้อมูลตามชุด) ภาพอื่นๆ ควรแสดงข้อมูลต่อไปนี้:When user selects Import Car by Type (selects data by series), other visuals should show following data:

ผู้ผลิตManufacturer ชนิดType ค่าValue
ไครสเลอร์Chrysler รถนำเข้าImport Car 00
ฟอร์ดFord รถนำเข้าImport Car 00
GMGM รถนำเข้าImport Car 197197
ฮอนด้าHonda รถนำเข้าImport Car 29322932
นิสสันNissan รถนำเข้าImport Car 54855485
โตโยต้าToyota รถนำเข้าImport Car 2079920799

การแสดงผลด้วยภาพที่เลือกสำหรับประเภทและชุดข้อมูล

จำเป็นต้องเติมตะกร้าข้อมูลด้วยภาพNeed to fill the visual data baskets.

ตะกร้าข้อมูลของภาพที่มีการเลือก

มี Manufacturer เป็นประเภท (คอลัมน์) Type เป็นชุดข้อมูล (แถว) และ Value เป็น Values สำหรับชุดข้อมูลThere are Manufacturer as category (columns), Type as series (rows) and Value as Values for series.

หมายเหตุ

จำเป็นต้องมี Values สำหรับชุดข้อมูลเนื่องจากการแมปมุมมองข้อมูลตามวิชวลคาดหวังว่า Values จะถูกจัดกลุ่มตามข้อมูล RowsThe Values are required for series because according to data view mapping the visual expects that Values will be grouped by Rows data.

สร้างการเลือกสำหรับประเภทCreate selections for categories

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

ในโค้ดตัวอย่าง คุณจะเห็นว่าเราวนซ้ำทุกหมวดหมู่In the sample code, you can see that we iterate all categories. และในแต่ละการวนซ้ำ เราเรียกใช้ createSelectionIdBuilder เพื่อสร้างการเลือกถัดไปสำหรับแต่ละหมวดหมู่โดยการเรียกเมธอด withCategory ของตัวสร้างการเลือกAnd in each iteration, we call createSelectionIdBuilder to create the next selection for each category by calling withCategory method of the selection builder. เมธอด createSelectionId ถูกใช้เป็นเมธอดสุดท้ายในการส่งกลับออบเจ็กต์ selection ที่สร้างขึ้นThe method createSelectionId is used as a final method to return the generated selection object.

ในเมธอด withCategory เราส่งผ่านคอลัมน์ของ category ในตัวอย่าง ซึ่งคือ Manufacturer และดัชนีขององค์ประกอบหมวดหมู่In withCategory method, we pass the column of category, in the sample, it's Manufacturer and index of category element.

สร้างการเลือกสำหรับชุดข้อมูลCreate selections for series

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

สร้างการเลือกสำหรับการแมปมุมมองข้อมูลตารางCreate selections for table data view mapping

ตัวอย่างของการแมปมุมมองข้อมูลตารางSample of table data views mapping

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

หากต้องการสร้างการเลือกสำหรับการแมปมุมมองข้อมูลแบบตารางแต่ละแถว คุณต้องเรียกใช้เมธอด withTable ของตัวสร้างการเลือกTo create a selection for each row of table data view mapping, you need to call withTable method of selection builder.

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

โค้ดของวิชวลจะวนซ้ำแถวของตาราง และแต่ละแถวเรียกเมธอดตาราง withTableThe visual code iterates the rows of the table and each row calls withTable table method. พารามิเตอร์ของวิธีการ withTable คือวัตถุ table และดัชนีของแถวตารางParameters of withTable method are table object and index of the table row.

สร้างการเลือกสำหรับการแมปมุมมองข้อมูลเมทริกซ์Create selections for matrix data view mapping

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

ในตัวอย่าง nodeWalker เรียกซ้ำสำหรับแต่ละโหนดและโหนดย่อยIn the sample, nodeWalker calls recursively for each node and child nodes.

nodeWalker สร้างวัตถุ nodeSelection ในการโทรแต่ละครั้งnodeWalker creates nodeSelection object on each call. และแต่ละ nodeSelection เป็นตัวแทน selection ของโหนดที่ตรงกันAnd each nodeSelection represent selection of correspond nodes.

เลือกจุดข้อมูลเพื่อแบ่งภาพอื่นๆSelect datapoints to slice other visuals

ในตัวอย่าง โค้ดของการเลือกสำหรับการแมปมุมมองข้อมูลแบบจัดกลุ่ม คุณเห็นว่าเราได้สร้างตัวจัดการการคลิกสำหรับองค์ประกอบปุ่มIn the sample, codes of selections for categorical data view mapping, you saw that we created a click handler for button elements. ตัวจัดการเรียกเมธอด select ของตัวจัดการการเลือกและส่งผ่านออบเจ็กต์การเลือกThe handler calls select method of the selection manager and passes the selection object.

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

อินเทอร์เฟซของวิธีการ select คือThe interface of select method is

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

คุณสามารถดู select สามารถยอมรับอาร์เรย์ของการเลือกได้You can see select can accept an array of selections. ซึ่งหมายความว่าภาพของคุณสามารถเลือกหลายจุดข้อมูลได้It means your visual can select several datapoints. พารามิเตอร์ตัวที่สอง multiSelect รับผิดชอบการเลือกหลายรายการThe second parameter multiSelect responsible for multi-select. ถ้าค่าเป็นจริง Power BI จะไม่ล้างสถานะการเลือกก่อนหน้าและใช้การเลือกปัจจุบัน มิฉะนั้นการเลือกก่อนหน้าจะรีเซ็ตIf the value is true, Power BI doesn't clear the previous selection state and apply current selection otherwise previous selection will reset.

สถานการณ์โดยทั่วไปของการใช้การจัดการ multiSelect ของปุ่ม CTRL สำหรับการคลิกเหตุการณ์The typical scenario of using multiSelect handling CTRL button state on click event.

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

ขั้นตอนถัดไปNext steps