Creare una finestra di dialogo per l'oggetto visivo di Power BI

Quando si crea un oggetto visivo, a volte è utile visualizzare informazioni aggiuntive al cliente in una finestra separata. Può, ad esempio, essere necessario:

  • Mostra informazioni aggiuntive, ad esempio una nota di testo o un video
  • Visualizzare una finestra di dialogo dati di input, ad esempio una finestra di dialogo data

A questo scopo, è possibile creare una finestra popup dell'oggetto visivo della finestra di dialogo, denominata finestra di dialogo in questo articolo.

Considerazioni sulla finestra di dialogo

Quando si crea una finestra di dialogo per l'oggetto visivo, tenere presente che:

  • Durante lo sviluppo, è possibile specificare le dimensioni e la posizione della finestra di dialogo.
  • Quando viene attivata la finestra di dialogo, lo sfondo del report è disattivato.
  • L'intestazione della finestra di dialogo contiene l'icona dell'oggetto visivo e il relativo nome visualizzato come titolo.
  • La finestra di dialogo può avere fino a tre pulsanti di azione. È possibile scegliere quali pulsanti visualizzare da una determinata selezione.
  • La finestra di dialogo usa un codice HTML iframeavanzato.
  • Mentre viene visualizzata la finestra di dialogo, non è possibile eseguire alcuna azione nel report fino a quando non viene chiusa.
  • Il codice del dialogo può usare librerie npm esterne, proprio come l'oggetto visivo.

Importante

La finestra di dialogo non deve essere attivata spontaneamente. Deve essere il risultato immediato di un'azione dell'utente.

Progettare una finestra di dialogo per l'oggetto visivo

Per configurare una finestra di dialogo, è necessario aggiungere due componenti al codice:

Creare il file di implementazione della finestra di dialogo

È consigliabile creare un file di implementazione per ogni finestra di dialogo creata. Inserire i file della finestra di dialogo nella src cartella :

Screenshot showing the location of a dialog box implementation file called DatePickerDialog.ts in a Power BI visuals project.

Ogni file di implementazione della finestra di dialogo deve includere i componenti seguenti:

Creare una classe della finestra di dialogo

Creare una classe di finestra di dialogo per la finestra di dialogo. Il initialState parametro in openModalDialog viene passato al collaboratore del dialogo al momento della creazione. Utilizzare l'oggetto initialState per passare i parametri alla finestra di dialogo, per influire sul comportamento o sull'aspetto.

Il codice della finestra di dialogo può usare questi IDialogHost metodi:

  • IDialogHost.setResult(result:object) - Il codice della finestra di dialogo restituisce un oggetto risultato passato all'oggetto visivo chiamante.
  • IDialogHost.close(actionId: DialogAction, result?:object) - Il codice della finestra di dialogo può chiudere il dialogo a livello di codice e fornire un oggetto risultato all'oggetto visivo chiamante.

Importazioni all'inizio del file:

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';

Questo esempio richiede l'installazione di questi pacchetti:

    npm i react-dom react react-datepicker

Realizzazione classe:

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

Creare una classe di risultati

Creare una classe che restituisca il risultato della finestra di dialogo e quindi aggiungerla al file di implementazione della finestra di dialogo.

Nell'esempio seguente la DatePickerDialogResult classe restituisce una stringa di data.

export class DatePickerDialogResult {
    date: string;
}

Aggiungere la finestra di dialogo all'elenco del Registro di sistema

Ogni file di implementazione del dialogo deve includere un riferimento al Registro di sistema. Aggiungere le due righe nell'esempio seguente alla fine del file di implementazione della finestra di dialogo. La prima riga deve essere identica in ogni file di implementazione della finestra di dialogo. La seconda riga elenca la finestra di dialogo; modificarlo in base al nome della classe della finestra di dialogo.

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

Richiamare la finestra di dialogo

Prima di creare una finestra di dialogo, è necessario decidere quali pulsanti includeranno. Gli oggetti visivi di Power BI supportano i sei pulsanti di finestra di dialogo seguenti:

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

Ogni finestra di dialogo creata deve essere richiamata nel visual.ts file. In questo esempio la finestra di dialogo viene definita con due pulsanti di azione.

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

In questo esempio la finestra di dialogo viene richiamata facendo clic su un pulsante di visualizzazione. Il pulsante dell'oggetto visivo viene definito come parte del costruttore visivo nel visual.ts file.

Definire le dimensioni e la posizione della finestra di dialogo

Dall'API versione 4.0 o successiva è possibile definire le dimensioni e la posizione della finestra di dialogo usando il DialogOpenOptions parametro di openModalDialog. Per scoprire quale versione si sta usando, archiviare apiVersion il file pbiviz.json .

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

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

Il parametro position consente di decidere dove aprire la finestra di dialogo sullo schermo. È possibile scegliere di aprire la finestra di dialogo al centro dello schermo oppure definire una posizione diversa rispetto all'oggetto visivo.

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

    export interface VisualDialogPosition {
        type: VisualDialogPositionType;
        left?: number;
        top?: number;
    }
  • Se non viene specificato alcun tipo, il comportamento predefinito consiste nell'aprire la finestra di dialogo al centro.
  • La posizione viene specificata in pixel rispetto all'angolo superiore sinistro dell'oggetto visivo.

Questo esempio mostra una finestra di dialogo di selezione data 250 x 300 pixel da 100 pixel a sinistra e 30 pixel sotto la parte superiore dell'oggetto visivo:

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

Definire come chiudere la finestra di dialogo

Il metodo preferito per la chiusura della finestra di dialogo è da parte dell'utente finale che fa clic sul pulsante [x], uno dei pulsanti di azione o sullo sfondo del report.

È anche possibile programmare la finestra di dialogo per chiudere automaticamente chiamando il IDialogHost metodo close. Questo metodo viene bloccato per cinque secondi dopo l'apertura della finestra di dialogo, in modo che il primo che è possibile chiudere automaticamente la finestra di dialogo è di cinque secondi dopo l'avvio.

Non visualizzare la finestra di dialogo

La finestra di dialogo viene visualizzata con una casella di controllo che consente all'utente di bloccare le finestre di dialogo.

Screenshot showing a checkbox giving the option to block dialog boxes.

Questa casella di controllo è una funzionalità di sicurezza che impedisce all'oggetto visivo di creare finestre di dialogo modali (intenzionalmente o meno) senza il consenso dell'utente.

Questo blocco è attivo solo per la sessione corrente. Pertanto, se un utente blocca i dialoghi modali cv, ma in seguito cambia idea, può riabilitare i dialoghi. A tale scopo, è necessario avviare una nuova sessione (aggiornare la pagina dei report in servizio Power BI o riavviare Power BI Desktop).

Considerazioni e limitazioni

  • A partire da powerbi-visuals-API 3.8, l'icona e il titolo della finestra di dialogo sono determinati dall'icona dell'oggetto visivo e dal nome visualizzato e non possono essere modificati.

  • Le limitazioni delle dimensioni della finestra di dialogo sono descritte nella tabella seguente.

    Max/min Larghezza Altezza
    Massimo 90% della larghezza del browser 90% dell'altezza del browser
    Requisiti minimi 240 px 210 px
  • Quando si definisce la posizione della finestra di dialogo, la posizione orizzontale può essere un numero intero positivo o negativo, a seconda del lato dell'oggetto visivo che si desidera che la casella sia. La posizione verticale non può essere negativa, in quanto la posizione viene posizionata sopra l'oggetto visivo.

  • Le funzionalità seguenti non supportano la finestra di dialogo Oggetti visivi di Power BI:

    • Analisi incorporate
    • Pubblica sul Web
    • Dashboard

È possibile programmare l'oggetto visivo per rilevare se l'ambiente corrente consente di aprire una finestra di dialogo selezionando il valore booleano this.host.hostCapabilities.allowModalDialog.