Power BI ビジュアルに対してダイアログ ボックスを作成する

ビジュアルを作成するときに、別のウィンドウで顧客に追加情報を表示すると便利な場合があります。 たとえば、次の操作を行います。

  • 追加情報を表示する - テキスト メモやビデオなど。
  • 入力データのダイアログ ボックスを表示する - 日付のダイアログ ボックスなど。

このような目的のために、ダイアログのビジュアル ポップアップ ウィンドウを作成できます。この記事ではこれを "ダイアログ ボックス" と呼びます。

ダイアログ ボックスに関する考慮事項

ビジュアルに対してダイアログ ボックスを作成する際は、次の点をご考慮ください。

  • 開発時に、ダイアログ ボックスのサイズと位置を指定できます。
  • ダイアログ ボックスがトリガーされると、レポートの背景がグレー表示になります。
  • ダイアログ ヘッダーには、ビジュアルのアイコンとその表示名がタイトルとして含まれます。
  • ダイアログ ボックスには、最大 3 つのアクション ボタンを含めることができます。 特定の選択範囲からどのボタンを表示するかを選択できます。
  • ダイアログ ボックスにはリッチ HTML の iframe が使用されます。
  • ダイアログ ボックスが表示されている間は、それが閉じられるまで、レポートで操作を実行することはできません。
  • ダイアログ コードでは、ビジュアルと同じように、外部の npm ライブラリを使用することができます。

重要

ダイアログ ボックスを自動的に起動することはできません。 これはユーザー アクションの即時の結果です。

ビジュアルのダイアログ ボックスをデザインする

ダイアログ ボックスを構成するには、コードに 2 つのコンポーネントを追加する必要があります。

ダイアログ ボックスの実装ファイルを作成する

作成するダイアログ ボックスごとに実装ファイルを作成することをお勧めします。 ダイアログ ボックス ファイルを src フォルダーに配置します。

Power BI ビジュアル プロジェクト内の DatePickerDialog.ts というダイアログ ボックス実装ファイルの場所を示すスクリーンショット。

各ダイアログ ボックスの実装ファイルには、次のコンポーネントが含まれている必要があります。

ダイアログ ボックス クラスを作成する

ダイアログ ボックスのダイアログ ボックス クラスを作成します。 openModalDialoginitialState パラメーターは、作成時にダイアログ コントラクターに渡されます。 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;
}

レジストリの一覧にダイアログ ボックスを追加する

すべてのダイアログ実装ファイルにレジストリ参照を含める必要があります。 以下の例内の 2 行を、ダイアログ ボックス実装ファイルの末尾に追加します。 最初の行は、すべてのダイアログ ボックス実装ファイルで同一である必要があります。 2 行目でダイアログ ボックスを表示し、それをダイアログ ボックス クラスの名前に従って変更します。

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

ダイアログ ボックスを起動する

ダイアログ ボックスを作成する前に、どのボタンを含めるかを決定する必要があります。 Power BI ビジュアルでは、次の 6 つのダイアログ ボックス ボタンがサポートされています。

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

作成する各ダイアログ ボックスは、visual.ts ファイルで呼び出す必要があります。 この例では、ダイアログ ボックスに 2 つのアクション ボタンが定義されています。

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;
    }
  • type が指定されていない場合、既定の動作ではダイアログ ボックスは中央に開かれます。
  • 位置は視覚エフェクトの左上を基準としてピクセル単位で指定されます。

この例では、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 をチェックすることで、現在の環境でダイアログ ボックスを開くことができるかどうかを検出するようにビジュアルをプログラムできます。