分享方式:


為您的 Power BI 視覺效果建立對話方塊

當您建立視覺效果時,有時在另一個視窗中向客戶顯示其他資訊會很有用。 例如,您可能要:

  • 顯示其他資訊 - 例如文字記事或影片
  • 顯示輸入資料對話方塊 - 例如日期對話方塊

基於這些目的,您可以建立對話方塊視覺效果快顯視窗,在本文中,我們稱之為「對話方塊」

對話方塊的考量

在為視覺效果建立對話方塊時,請記住:

  • 在開發期間,您可以指定對話方塊的大小和位置。
  • 對話方塊觸發時,報表背景會呈現灰色。
  • 對話方塊標頭會包含視覺效果的圖示,並以其顯示名稱作為標題。
  • 對話方塊最多可以有三個動作按鈕。 您可以選擇要從指定選取範圍顯示的按鈕。
  • 對話方塊會使用 Rich HTML iframe
  • 對話方塊顯示時,您便無法在報表中執行任何動作,要等到對話方塊關閉才行。
  • 和視覺效果一樣,對話方塊的程式碼可以使用外部 npm 程式庫。

重要

對話方塊不應自發觸發。 其應該是使用者動作所導致的立即結果。

設計視覺效果的對話方塊

若要設定對話方塊,您需要將兩個元件新增至您的程式碼:

建立對話方塊實作檔案

建議您為所建立的每個對話方塊建立實作檔案。 將對話方塊檔案放在 src 資料夾中:

此螢幕擷取畫面顯示 Power BI 視覺效果專案中稱為 DatePickerDialog.ts 之對話方塊實作檔案的位置。

每個對話方塊實作檔案都應該包含下列元件:

建立對話方塊類別

請為您的對話方塊建立對話方塊類別。 openModalDialog 中的 initialState 參數會在建立時傳遞至對話方塊承攬者。 請使用 initialState 物件將參數傳遞至對話方塊,以影響其行為或外觀。

對話方塊程式碼可以使用下列 IDialogHost 方法:

  • IDialogHost.setResult(result:object) - 對話方塊程式碼會傳回結果物件,此結果物件則會傳遞回到其呼叫端視覺效果。
  • IDialogHost.close(actionId: DialogAction, result?:object) - 對話方塊程式碼能以程式設計方式關閉對話方塊,並將結果物件提供給其呼叫端視覺效果。

在檔案頂端匯入:

import powerbi from "powerbi-visuals-api";
import DialogConstructorOptions = powerbi.extensibility.visual.DialogConstructorOptions;
import DialogAction = powerbi.DialogAction;
// React imports as an example
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import reactDatepicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

這個範例需要安裝這些套件:

    npm i react-dom react react-datepicker

類別實現:

export class DatePickerDialog {
    static id = "DatePickerDialog";

    constructor(options: DialogConstructorOptions, initialState: object) {
        const host = options.host;
        let pickedDate: Date;
        const startDate = new Date(initialState['startDate']);
        
        // Dialog rendering implementation
        ReactDOM.render(
            React.createElement(
                reactDatepicker,
                {
                    inline: true,
                    openToDate: startDate,
                    onChange: (date: Date) => {
                        pickedDate = date
                        host.setResult({ date: pickedDate })
                    }
                },
                null),
            options.element
        );

        document.addEventListener('keydown', e => {
            if (e.code == 'Enter' && pickedDate) {
                host.close(DialogAction.Close, {date: pickedDate});
            }
        });
    }
}

建立結果類別

建立會傳回對話方塊結果的類別,然後將其新增至對話方塊實作檔案。

在下列範例中,DatePickerDialogResult 類別會傳回日期字串。

export class DatePickerDialogResult {
    date: string;
}

將對話方塊新增至登錄清單

每個對話方塊實作檔案都必須包含登錄參考。 將下列範例中的兩行新增至對話方塊實作檔案的結尾。 第一行在每個對話方塊實作檔案中應該都一樣。 第二行會列出您的對話方塊;請根據對話方塊類別的名稱加以修改。

globalThis.dialogRegistry = globalThis.dialogRegistry || {};
globalThis.dialogRegistry[DatePickerDialog.id] = DatePickerDialog;

叫用對話方塊

在建立對話方塊之前,您必須決定其會包含哪些按鈕。 Power BI 視覺效果支援下列六個對話方塊按鈕:

export enum DialogAction {
        Close = 0,
        OK = 1,
        Cancel = 2,
        Continue = 3,
        No = 4,
        Yes = 5
    }

您建立的每個對話方塊都必須在 visual.ts 檔案中叫用。 在此範例中,會以兩個動作按鈕來定義對話方塊。

import powerbi from "powerbi-visuals-api";
import DialogAction = powerbi.DialogAction;
const dialogActionsButtons = [DialogAction.OK, DialogAction.Cancel];

在此範例中,會按一下視覺效果按鈕來叫用對話方塊。 視覺效果按鈕會定義為 visual.ts 檔案中視覺效果建構函式的一部分。

定義對話方塊的大小和位置

從 API 4.0 版或更新版本開始,您可以使用 openModalDialogDialogOpenOptions 參數來定義對話方塊的大小和位置。 若要了解您正在使用哪個版本,請檢查 pbiviz.json 檔案中的 apiVersion

    export interface RectSize {
        width: number;
        height: number;
    }

    export interface DialogOpenOptions {
        title: string;
        size?: RectSize;
        position?: VisualDialogPosition;
        actionButtons: DialogAction[];
    }

position 參數可讓您決定應該在畫面上開啟對話方塊的位置。 您可以選擇在畫面中央開啟對話方塊,也可以定義相對於視覺效果的不同位置。

    const enum VisualDialogPositionType {
        Center = 0,
        RelativeToVisual = 1
    }

    export interface VisualDialogPosition {
        type: VisualDialogPositionType;
        left?: number;
        top?: number;
    }
  • 如果未指定任何類型,預設行為是在中央開啟對話方塊。
  • 系統會以像素為單位來指定相對於視覺效果左上角的位置。

此範例顯示 250 x 300 像素的日期選取對話方塊,在視覺效果左邊 100 像素,在視覺效果頂端下方 30 像素:

export class Visual implements IVisual {
    private target: HTMLElement;
    private host: IVisualHost;
 
    constructor(options: VisualConstructorOptions) {
        this.host = options.host;
        this.target = options.element;
        const dialogActionsButtons = [DialogAction.OK, DialogAction.Cancel];

        const sectionDiv = document.createElement("div");

        const span = document.createElement("span");
        span.id = "datePicker";

        let button = document.createElement("button");
        button.id = "DateButton";
        button.innerText = "Date";

        button.onclick = (event) => {
            const initialDialogState = { startDate: new Date() };
            const position = {
                    type: VisualDialogPositionType.RelativeToVisual,
                    left: 100,
                    top: 30
            };

            const size = {width: 250, height: 300};
            const dialogOptions = {
                actionButtons: dialogActionsButtons,
                size: size,
                position: position,
                title: "Select a date"
            };
            this.host.openModalDialog(DatePickerDialog.id, dialogOptions, initialDialogState).
                then(ret => this.handleDialogResult(ret, span)).
                catch(error => this.handleDialogError(error, span));
        }
        sectionDiv.appendChild(button);
        sectionDiv.appendChild(span);
        this.target.appendChild(sectionDiv)
    }

    // Custom logic to handle dialog results
    private handleDialogResult( result: ModalDialogResult, targetElement: HTMLElement){
        if ( result.actionId === DialogAction.OK || result.actionId === DialogAction.Close) {
            const resultState = <DatePickerDialogResult> result.resultState;
            const selectedDate = new Date(resultState.date);
            targetElement.textContent = selectedDate.toDateString();
        }
    }

    // Custom logic to handle errors in dialog
    private handleDialogError( error: any, targetElement: HTMLElement ) {
        targetElement.textContent = "Error: " + JSON.stringify(error);
    }
}

定義如何關閉對話方塊

關閉對話方塊的慣用方法是讓使用者按一下 [x] 按鈕、其中一個動作按鈕,或報表背景。

您也能以程式設計方式將對話方塊設定為會呼叫 IDialogHost close 方法來自動關閉。 在對話方塊開啟後,系統會將這個方法封鎖 5 秒,因此您可以自動關閉對話方塊的最早時間是在對話方塊起始 5 秒後。

不要顯示對話方塊

對話方塊出現時,會有核取方塊讓使用者選擇封鎖對話方塊。

顯示可供選擇封鎖對話方塊之核取方塊的螢幕擷取畫面。

此核取方塊是一項安全性功能,可防止視覺效果在沒有使用者同意的情況下,建立強制回應對話方塊 (無論是否刻意為之)。

此封鎖只會對目前的工作階段生效。 因此,如果使用者封鎖 CV 強制回應對話方塊,但之後改變心意,其可以重新啟用對話方塊。 若要這樣做,其需要啟動新的工作階段 (重新整理 Power BI 服務中的報表頁面,或重新啟動 Power BI Desktop)。

考量與限制

  • 從 powerbi-visuals-API 3.8 開始,對話方塊圖示和標題便由視覺效果的圖示和顯示名稱決定,無法加以變更。

  • 下表說明對話方塊的大小限制。

    最大值/最小值 寬度 高度
    最大值 瀏覽器寬度的 90% 瀏覽器高度的 90%
    最小值 240 px 210 px
  • 在定義對話方塊的位置時,視您希望方塊位於視覺效果哪一側而定,水平位置可以是正整數或負整數。 垂直位置不能是負數,因為這會讓其位於視覺效果上方。

  • 下列功能不支援 Power BI 視覺效果對話方塊:

    • 內嵌式分析
    • 發佈至 Web
    • 儀表板​​

您可以藉由檢查布林值 this.host.hostCapabilities.allowModalDialog,以程式設計方式將視覺效果設定為會偵測目前環境是否允許開啟對話方塊。