Share via


เพิ่มการสนับสนุนการดูรายละเอียดแนวลึก

เมื่อวิชวลมีลําดับชั้น คุณสามารถอนุญาตให้ผู้ใช้ใช้คุณลักษณะการดูรายละเอียดแนวลึกของ Power BI เพื่อดูรายละเอียดเพิ่มเติม

อ่านเพิ่มเติมเกี่ยวกับคุณลักษณะการดูรายละเอียดแนวลึกของ Power BI ที่โหมดดูรายละเอียดแนวลึกในบริการของ Power BI เมื่อต้องการอนุญาตให้วิชวลเปิดใช้งานหรือปิดใช้งานคุณลักษณะการดูรายละเอียดแบบไดนามิก ดู ตัวควบคุมการดูรายละเอียดแนวลึกแบบไดนามิก

เปิดใช้งานการสนับสนุนการดูรายละเอียดแนวลึกในวิชวล

เพื่อสนับสนุนการดําเนินการดูรายละเอียดแนวลึกในวิชวลของคุณ ให้เพิ่มเขตข้อมูลใหม่ลงใน capabilities.json ที่มี drill-downชื่อ เขตข้อมูลนี้มีหนึ่งคุณสมบัติที่เรียกว่า roles ที่ประกอบด้วยชื่อของ dataRole ที่คุณต้องการเปิดใช้งานการดําเนินการดูรายละเอียดแนวลึก

    "drilldown": {
        "roles": [
            "category"
        ]
    }

หมายเหตุ

dataRole การดูรายละเอียดแนวลึกต้องเป็นชนิดGrouping max คุณสมบัติ ในเงื่อนไข dataRole ต้องได้รับการตั้งค่าเป็น 1

เมื่อคุณเพิ่มบทบาทลงในเขตข้อมูลการดูรายละเอียดแนวลึก ผู้ใช้สามารถลากหลายเขตข้อมูลลงในบทบาทข้อมูลได้

ตัวอย่างเช่น:

{
    "dataRoles": [
        {
            "displayName": "Category",
            "name": "category",
            "kind": "Grouping"
        },
        {
            "displayName": "Value",
            "name": "value",
            "kind": "Measure"
        }
    ],
    "drilldown": {
        "roles": [
            "category"
        ]
    },
    "dataViewMappings": [
        {
            "categorical": {
                "categories": {
                    "for": {
                        "in": "category"
                    }
                },
                "values": {
                    "select": [
                        {
                            "bind": {
                                "to": "value"
                            }
                        }
                    ]
                }
            }
        }
    ]
}

สร้างวิชวลที่มีการสนับสนุนการดูรายละเอียดแนวลึก

หากต้องการสร้างวิชวลที่มีการสนับสนุนการดูรายละเอียดแนวลึก ให้เรียกใช้คําสั่งต่อไปนี้:

pbiviz new testDrillDown -t default

หากต้องการสร้างวิชวลตัวอย่างเริ่มต้น ให้ใช้ตัวอย่างด้านบนของ capabilities.json กับวิชวลที่สร้างขึ้นใหม่

สร้างคุณสมบัติ สําหรับ div คอนเทนเนอร์ เพื่อเก็บองค์ประกอบ HTML ของวิชวล:

"use strict";

import "core-js/stable";
import "./../style/visual.less";
// imports

export class Visual implements IVisual {
    // visual properties
    // ...
    private div: HTMLDivElement; // <== NEW PROPERTY

    constructor(options: VisualConstructorOptions) {
        // constructor body
        // ...
    }

    public update(options: VisualUpdateOptions) {
        // update method body
        // ...
    }

    /**
     * Returns properties pane formatting model content hierarchies, properties and latest formatting values, Then populate properties pane.
     * This method is called once each time we open the properties pane or when the user edits any format property. 
     */
    public getFormattingModel(): powerbi.visuals.FormattingModel {
        return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
    }
}

อัปเดตคอนสตรักเตอร์ของวิชวล:


export class Visual implements IVisual {
    // visual properties
    // ...
    private div: HTMLDivElement;

    constructor(options: VisualConstructorOptions) {
        console.log('Visual constructor', options);
        this.formattingSettingsService = new FormattingSettingsService();
        this.target = options.element;
        this.updateCount = 0;

        if (document) {
            const new_p: HTMLElement = document.createElement("p");
            new_p.appendChild(document.createTextNode("Update count:"));
            const new_em: HTMLElement = document.createElement("em");
            this.textNode = document.createTextNode(this.updateCount.toString());
            new_em.appendChild(this.textNode);
            new_p.appendChild(new_em);
            this.div = document.createElement("div"); // <== CREATE DIV ELEMENT
            this.target.appendChild(new_p);
        }
    }
}

หากต้องการสร้าง buttonให้อัปเดต update วิธีการ ของวิชวล:

export class Visual implements IVisual {
    // ...

    public update(options: VisualUpdateOptions) {
        this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
        console.log('Visual update', options);

        const dataView: DataView = options.dataViews[0];
        const categoricalDataView: DataViewCategorical = dataView.categorical;

        // don't create elements if no data
        if (!options.dataViews[0].categorical ||
            !options.dataViews[0].categorical.categories) {
            return
        }

        // to display current level of hierarchy
        if (typeof this.textNode !== undefined) {
            this.textNode.textContent = categoricalDataView.categories[categoricalDataView.categories.length - 1].source.displayName.toString();
        }

        // remove old elements
        // for better performance use D3js pattern:
        // https://d3js.org/#enter-exit
        while (this.div.firstChild) {
            this.div.removeChild(this.div.firstChild);
        }

        // create buttons for each category value
        categoricalDataView.categories[categoricalDataView.categories.length - 1].values.forEach( (category: powerbi.PrimitiveValue, index: number) => {
            let button = document.createElement("button");
            button.innerText = category.toString();

            this.div.appendChild(button);
        })

    }
    // ...

ใช้ลักษณะอย่างง่ายใน .\style\visual.less:

button {
    margin: 5px;
    min-width: 50px;
    min-height: 50px;
}

เตรียมข้อมูลตัวอย่างสําหรับการทดสอบวิชวล:

H1 H2 H3 ค่า
A1 A11 1
A1 A12 2
A2 A21 3
A2 A22 4
A3 A31 5
A3 A32 6
B B1 B11 7
B B1 B12 8
B B2 B21 9
B B2 B22 10
B B3 B31 11
B B3 B32 12

และสร้างลําดับชั้นใน Power BI Desktop:

Screenshot shows the Power B I Desktop with New hierarchy selected in a contextual menu.

รวมคอลัมน์หมวดหมู่ทั้งหมด (H1, H2, H3) ไปยังลําดับชั้นใหม่:

Screenshot shows category columns you can add to the new hierarchy.

หลังจากขั้นตอนเหล่านั้นคุณควรได้รับวิชวลต่อไปนี้:

Dev visual with buttons

เพิ่มเมนูบริบทไปยังองค์ประกอบวิชวล

เมื่อต้องเพิ่มเมนูบริบทไปยังปุ่มบนวิชวล:

Context menu in the visual

บันทึก host วัตถุในคุณสมบัติของวิชวลและเรียกใช้ createSelectionManager เมธอด เพื่อสร้างตัวจัดการการเลือกเพื่อแสดงเมนูบริบทโดยใช้ Power BI Visuals API

"use strict";

import "core-js/stable";
import "./../style/visual.less";
// default imports

import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import ISelectionManager = powerbi.extensibility.ISelectionManager;
import ISelectionId = powerbi.visuals.ISelectionId;

export class Visual implements IVisual {
    // visual properties
    // ...
    private div: HTMLDivElement;
    private host: IVisualHost; // <== NEW PROPERTY
    private selectionManager: ISelectionManager; // <== NEW PROPERTY

    constructor(options: VisualConstructorOptions) {
        // constructor body
        // save the host in the visuals properties
        this.host = options.host;
        // create selection manager
        this.selectionManager = this.host.createSelectionManager();
        // ...
    }

    public update(options: VisualUpdateOptions) {
        // update method body
        // ...
    }

    // ...
}

เปลี่ยนเนื้อความของ forEach การเรียกกลับฟังก์ชันเป็น:

    categoricalDataView.categories[categoricalDataView.categories.length - 1].values.forEach( (category: powerbi.PrimitiveValue, index: number) => {
        // create selectionID for each category value
        let selectionID: ISelectionId = this.host.createSelectionIdBuilder()
            .withCategory(categoricalDataView.categories[0], index)
            .createSelectionId();

        let button = document.createElement("button");
        button.innerText = category.toString();

        // add event listener to click event
        button.addEventListener("click", (event) => {
            // call select method in the selection manager
            this.selectionManager.select(selectionID);
        });

        button.addEventListener("contextmenu", (event) => {
            // call showContextMenu method to display context menu on the visual
            this.selectionManager.showContextMenu(selectionID, {
                x: event.clientX,
                y: event.clientY
            });
            event.preventDefault();
        });

        this.div.appendChild(button);
    });

นําข้อมูลไปใช้กับวิชวล:

Screenshot shows the hierarchy with H2 called out.

ในขั้นตอนสุดท้าย คุณควรได้รับวิชวลที่มีการเลือกและเมนูบริบท:

Animation shows selecting Drill down and Drill up from the visual context menu.

เพิ่มการสนับสนุนการดูรายละเอียดแนวลึกสําหรับการแมปมุมมองข้อมูลแบบเมทริกซ์

หากต้องการทดสอบวิชวลด้วยการแมปมุมมองข้อมูลแบบเมทริกซ์ ก่อนอื่นให้เตรียมข้อมูลตัวอย่าง:

แถวที่ 1 แถวที่ 2 แถวที่ 3 คอลัมน์ 1 คอลัมน์ 2 คอลัมน์ 3 ค่า
R1 R11 R111 C1 C11 C111 1
R1 R11 R112 C1 C11 C112 2
R1 R11 R113 C1 C11 C113 3
R1 R12 R121 C1 C12 C121 4
R1 R12 R122 C1 C12 C122 5
R1 R12 R123 C1 C12 C123 6
R1 R13 R131 C1 C13 C131 7
R1 R13 R132 C1 C13 C132 8
R1 R13 R133 C1 C13 C133 9
R2 R21 R211 C2 C21 C211 10
R2 R21 R212 C2 C21 C212 11
R2 R21 R213 C2 C21 C213 12
R2 R22 R221 C2 C22 C221 13
R2 R22 R222 C2 C22 C222 14
R2 R22 R223 C2 C22 C223 16
R2 R23 R231 C2 C23 C231 17
R2 R23 R232 C2 C23 C232 18
R2 R23 R233 C2 C23 C233 19

จากนั้นใช้การแมปมุมมองข้อมูลต่อไปนี้กับวิชวล:

{
    "dataRoles": [
        {
            "displayName": "Columns",
            "name": "columns",
            "kind": "Grouping"
        },
        {
            "displayName": "Rows",
            "name": "rows",
            "kind": "Grouping"
        },
        {
            "displayName": "Value",
            "name": "value",
            "kind": "Measure"
        }
    ],
    "drilldown": {
        "roles": [
            "columns",
            "rows"
        ]
    },
    "dataViewMappings": [
        {
            "matrix": {
                "columns": {
                    "for": {
                        "in": "columns"
                    }
                },
                "rows": {
                    "for": {
                        "in": "rows"
                    }
                },
                "values": {
                    "for": {
                        "in": "value"
                    }
                }
            }
        }
    ]
}

นําข้อมูลไปใช้กับวิชวล:

Screenshot shows the MatrixHierarchy with the columns and rows hierarchy and their members selected.

นําเข้าอินเทอร์เฟสที่จําเป็นเพื่อประมวลผลการแมปมุมมองข้อมูลแบบเมทริกซ์:

// ...
import DataViewMatrix = powerbi.DataViewMatrix;
import DataViewMatrixNode = powerbi.DataViewMatrixNode;
import DataViewHierarchyLevel = powerbi.DataViewHierarchyLevel;
// ...

สร้างคุณสมบัติสองรายการสําหรับองค์ประกอบแถวและคอลัมน์สอง divรายการ:

export class Visual implements IVisual {
    // ...
    private rowsDiv: HTMLDivElement;
    private colsDiv: HTMLDivElement;
    // ...
    constructor(options: VisualConstructorOptions) {
        // constructor body
        // ...
        // Create div elements and append to main div of the visual
        this.rowsDiv = document.createElement("div");
        this.target.appendChild(this.rowsDiv);

        this.colsDiv = document.createElement("div");
        this.target.appendChild(this.colsDiv);
    }
    // ...
}

ตรวจสอบข้อมูลก่อนแสดงองค์ประกอบและแสดงระดับลําดับชั้นปัจจุบัน:

export class Visual implements IVisual {
    // ...
    constructor(options: VisualConstructorOptions) {
        // constructor body
    }

    public update(options: VisualUpdateOptions) {
        this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews);
        console.log('Visual update', options);

        const dataView: DataView = options.dataViews[0];
        const matrixDataView: DataViewMatrix = dataView.matrix;

        // if the visual doesn't receive the data no reason to continue rendering
        if (!matrixDataView ||
            !matrixDataView.columns ||
            !matrixDataView.rows ) {
            return
        }

        // to display current level of hierarchy
        if (typeof this.textNode !== undefined) {
            this.textNode.textContent = categoricalDataView.categories[categoricalDataView.categories.length - 1].source.displayName.toString();
        }
        // ...
    }
    // ...
}

สร้างฟังก์ชัน treeWalker สําหรับการท่องไปตามลําดับชั้น:

export class Visual implements IVisual {
    // ...
    public update(options: VisualUpdateOptions) {
        // ...

        // if the visual doesn't receive the data no reason to continue rendering
        if (!matrixDataView ||
            !matrixDataView.columns ||
            !matrixDataView.rows ) {
            return
        }

        const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
            // ...
            if (matrixNode.children) {
                // ...
                // traversing child nodes
                matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
            }
        }

        // traversing rows
        const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
        rowRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.rows.levels, this.rowsDiv));

        // traversing columns
        const colRoot = matrixDataView.columns.root;
        colRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.columns.levels, this.colsDiv));
    }
    // ...
}

สร้างการเลือกสําหรับจุดข้อมูล

const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
    // generate selectionID for each node of matrix
    const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
        .withMatrixNode(matrixNode, levels)
        .createSelectionId();
    // ...
    if (matrixNode.children) {
        // ...
        // traversing child nodes
        matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
    }
}

สร้าง div สําหรับแต่ละระดับของลําดับชั้น:

const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
    // generate selectionID for each node of matrix
    const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
        .withMatrixNode(matrixNode, levels)
        .createSelectionId();
    // ...
    if (matrixNode.children) {
        // create div element for level
        const childDiv = document.createElement("div");
        // add to current div
        div.appendChild(childDiv);
        // create paragraph element to display next
        const p = document.createElement("p");
        // display level name on paragraph element
        const level = levels[matrixNode.level];
        p.innerText = level.sources[level.sources.length - 1].displayName;
        // add paragraph element to created child div
        childDiv.appendChild(p);
        // traversing child nodes
        matrixNode.children.forEach((node, index) => treeWalker(node, index, levels, childDiv));
    }
}

สร้าง buttons เพื่อโต้ตอบกับวิชวลและแสดงเมนูบริบทสําหรับจุดข้อมูลเมทริกซ์:

const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
    // generate selectionID for each node of matrix
    const selectionID: ISelectionID = this.host.createSelectionIdBuilder()
        .withMatrixNode(matrixNode, levels)
        .createSelectionId();

    // create button element
    let button = document.createElement("button");
    // display node value/name of the button's text
    button.innerText = matrixNode.value.toString();

    // add event listener on click
    button.addEventListener("click", (event) => {
        // call select method in the selection manager
        this.selectionManager.select(selectionID);
    });

    // display context menu on click
    button.addEventListener("contextmenu", (event) => {
        // call showContextMenu method to display context menu on the visual
        this.selectionManager.showContextMenu(selectionID, {
            x: event.clientX,
            y: event.clientY
        });
        event.preventDefault();
    });

    div.appendChild(button);

    if (matrixNode.children) {
        // ...
    }
}

ล้าง div องค์ประกอบก่อนที่จะแสดงองค์ประกอบอีกครั้ง:

public update(options: VisualUpdateOptions) {
    // ...
    const treeWalker = (matrixNode: DataViewMatrixNode, index: number, levels: DataViewHierarchyLevel[], div: HTMLDivElement)  => {
        // ...
    }

    // remove old elements
    // to better performance use D3js pattern:
    // https://d3js.org/#enter-exit
    while (this.rowsDiv.firstChild) {
        this.rowsDiv.removeChild(this.rowsDiv.firstChild);
    }
    // create label for row elements
    const prow = document.createElement("p");
    prow.innerText = "Rows";
    this.rowsDiv.appendChild(prow);

    while (this.colsDiv.firstChild) {
        this.colsDiv.removeChild(this.colsDiv.firstChild);
    }
    // create label for columns elements
    const pcol = document.createElement("p");
    pcol.innerText = "Columns";
    this.colsDiv.appendChild(pcol);

    // render elements for rows
    const rowRoot: DataViewMatrixNode = matrixDataView.rows.root;
    rowRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.rows.levels, this.rowsDiv));

    // render elements for columns
    const colRoot = matrixDataView.columns.root;
    colRoot.children.forEach((node, index) => treeWalker(node, index, matrixDataView.columns.levels, this.colsDiv));
}

สุดท้าย คุณควรได้รับวิชวลที่มีเมนูบริบท:

Animation shows a context menu for the visual with options to drill down or drill up.