Compartir a través de


Transformar cuadros de diálogo del modelo de complemento en diálogos modernos en SharePoint Framework

En el modelo de complementos de SharePoint, se usó para basarse en el modelo de objetos de JavaScript para SharePoint para mostrar ventanas de diálogo, con una sintaxis similar a la siguiente:

// Sample syntax to show a dialog window
var options = SP.UI.$create_DialogOptions();
options.url = '{SiteUrl}/_layouts/MyAddin/' + 'MyAddinDialog.aspx';
options.autoSize = true;
options.dialogReturnValueCallback = Function.createDelegate(null, dialogCloseCallback);
this.dialog = SP.UI.ModalDialog.showModalDialog(options);

// Function to handle dialog close callback
function dialogCloseCallback(result, returnValue) {
  if (result == SP.UI.DialogResult.OK) {
    window.alert('You clicked OK! And selected a status of: ' + returnValue);
  } else if (result == SP.UI.DialogResult.cancel) {
    window.alert('You clicked Cancel!');
  } 

  SP.UI.ModalDialog.RefreshPage(result);
}

Solo para crear un ejemplo, el código anterior se podría usar en la acción de una acción personalizada de la interfaz de usuario, en el Código JavaScript de un elemento web o en muchos otros lugares.

Hoy en día, con SharePoint Framework, puede confiar en SharePoint Framework Dialog Framework para lograr el mismo resultado e incluso más. En este artículo, puede encontrar información detallada sobre cómo transformar diálogos modales clásicos del modelo de complementos de SharePoint en SharePoint Framework diálogos modernos.

Si lo prefiere, puede watch el siguiente vídeo, en lugar de leer todo el artículo, que todavía puede considerar como una referencia mucho más detallada.

Transformar cuadros de diálogo del modelo de complemento en diálogos modernos en SharePoint Framework

Nota:

Puede encontrar más detalles sobre cómo aprovechar el marco de diálogo de SharePoint Framework leyendo el documento Uso de cuadros de diálogo personalizados con extensiones de SharePoint Framework.

Establecer el contexto

Imagine que tiene un elemento web personalizado con un botón "Crear tarea" y, cada vez que un usuario selecciona en ese botón, quiere abrir un cuadro de diálogo modal para recopilar información sobre una tarea hipotética que se crea.

En la captura de pantalla siguiente, puede ver el aspecto que debe tener esta solución.

Interfaz de usuario de un elemento web con un cuadro de diálogo modal personalizado para configurar las opciones específicas del usuario.

Creación de una solución de SharePoint Framework

Para lograr el resultado anterior, vamos a empezar por crear una nueva solución de SharePoint Framework.

En primer lugar, debe aplicar scaffolding a la solución SharePoint Framework, por lo que inicie un símbolo del sistema o una ventana de terminal, cree una carpeta y, desde dentro de la carpeta recién creada, ejecute el siguiente comando.

Importante

Para poder seguir el procedimiento ilustrado, debe tener SharePoint Framework instalado en el entorno de desarrollo. Puede encontrar instrucciones detalladas sobre cómo configurar el entorno leyendo el documento Configuración del entorno de desarrollo de SharePoint Framework.

yo @microsoft/sharepoint

Interfaz de usuario de la herramienta scaffolding en una ventana de PowerShell, al tiempo que crea un nuevo proyecto para un personalizador de aplicaciones de SharePoint Framework.

Siga las indicaciones para aplicar scaffolding a una solución para un personalizador de aplicaciones moderno. En concreto, realice las siguientes opciones cuando la herramienta le solicite:

  • ¿Cuál es el nombre de la solución? spo-sp-fx-dialog
  • ¿Cuál es el tipo de componente del lado cliente que se va a crear? WebPart
  • ¿Cómo se llama su elemento web? ShowDialog
  • ¿Qué plantilla desea usar? React

Con las respuestas anteriores, decidió crear una solución con el nombre spo-sp-fx-dialog, en la que habrá un elemento web personalizado con el nombre ShowDialog. Cuando haya terminado el scaffolding, simplemente puede abrir la carpeta actual mediante el editor de código que prefiera. Sin embargo, antes de abrir la solución debe agregar un paquete para tener compatibilidad con SharePoint Framework Dialog Framework. Para ello, ejecute los siguientes comandos:

npm i @microsoft/sp-dialog --save

De hecho, de forma predeterminada, la solución scaffolding de un elemento web SharePoint Framework no incluye el paquete dialog framework. Ahora puede abrir la solución en el editor de código que prefiera. Si su editor de código favorito es Microsoft Visual Studio Code, simplemente ejecute el siguiente comando:

code .

En la siguiente imagen, puede ver el esquema de la solución de SharePoint Framework generada.

Esquema de la solución generada SharePoint Framework.

Como puede ver, en la carpeta src/webparts hay una subcarpeta con el nombre showDialog que contiene el scaffolding básico para el elemento web de ejemplo. En función de la elección realizada al generar la solución, el elemento web se basa en React para representar su interfaz de usuario. Por lo tanto, podemos centrarnos en el componente de React definido en los componentes de carpeta de la subcarpeta del elemento web.

Definición de la ventana de diálogo

Agregue una nueva subcarpeta con el nombre sampleDialog en la subcarpeta components y cree tres archivos en ella:

  • ITaskDialogProps.tsx: define las propiedades de configuración de la ventana de diálogo personalizada.
  • ITaskDialogState.tsx: define el estado de la ventana de diálogo personalizada.
  • TaskDialog.tsx: representa la implementación real de la ventana de diálogo.

En el fragmento de código siguiente, puede ver la definición de la interfaz ITaskDialogProps.tsx .

export interface ITaskDialogProps {
    onSave: (description: string, dueDate: Date) => Promise<void>;
    onClose: () => Promise<void>;
}

La interfaz simplemente define un par de métodos que controlan los eventos cuando el usuario guarda la tarea y cuando el usuario selecciona en "Cancelar" para cerrar el cuadro de diálogo sin guardar la tarea.

Además, en el siguiente fragmento de código puede encontrar la definición de la interfaz para contener el estado del componente de diálogo.

export interface ITaskDialogState {
    description?: string;
    dueDate?: Date;
}

Define el estado para realizar un seguimiento de la descripción de la tarea y la fecha de vencimiento. Por último, en el siguiente fragmento de código, puede ver la implementación real del componente de diálogo.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ITaskDialogProps } from './ITaskDialogProps';
import { ITaskDialogState } from './ITaskDialogState';

import { BaseDialog, IDialogConfiguration } from '@microsoft/sp-dialog';
import {
    TextField,
    DatePicker,
    DayOfWeek,
    DefaultButton,
    PrimaryButton,
    DialogFooter,
    DialogContent
} from '@fluentui/react/lib';

class TaskDialogContent extends
    React.Component<ITaskDialogProps, ITaskDialogState> {
    
    constructor(props: ITaskDialogProps) {
        super(props);

        this.state = {
            description: '',
            dueDate: new Date()
        };
    }
    
    public render(): JSX.Element {
        return (<div>
            <DialogContent
                title="Create Task"
                onDismiss={this.props.onClose}>

            <div>
                <div>
                    <TextField label="Task description"
                        onChange={this._onDescriptionChange}
                        value={this.state.description} />
                </div>
                <div>
                    <DatePicker label="Task due date"
                        firstDayOfWeek={DayOfWeek.Monday}
                        placeholder="Select a due date..."
                        ariaLabel="Select a due date"
                        onSelectDate={this._onDueDateSelected}
                        value={this.state.dueDate} />
                </div>
            </div>

            <DialogFooter>
                <DefaultButton text="Cancel"
                        title="Cancel" onClick={this.props.onClose} />
                <PrimaryButton text="Create Task"
                        title="Create Task" onClick={async () => { await this.props.onSave(this.state.description, this.state.dueDate); }} />
            </DialogFooter>
        </DialogContent>
    </div>);
    }

    private _onDescriptionChange = (event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string): void => {
        this.setState({ description: newValue });
    }

    private _onDueDateSelected = (date: Date): void => {
        this.setState({ dueDate: date });
    }
}

export default class TaskDialog extends BaseDialog {

    /**
     * Constructor for the dialog window
     */
    constructor(
        public onSave: (description: string, dueDate: Date) => Promise<void>,
        public onClose: () => Promise<void>) {
        super({isBlocking: true});
    }
  
    public render(): void {
        ReactDOM.render(<TaskDialogContent
                onSave={this._save}
                onClose={this._close}
            />,
            this.domElement);
    }
  
    public getConfig(): IDialogConfiguration {
      return {
        isBlocking: true
      };
    }

    protected onAfterClose(): void {
        ReactDOM.unmountComponentAtNode(this.domElement);
    }

    private _save = async (description: string, dueDate: Date): Promise<void> => {
        await this.close();
        await this.onSave(description, dueDate);
    }
  
    private _close = async (): Promise<void> => {
        await this.close();
        await this.onClose();
    }
}

El archivo define un componente React con el nombre TaskDialogContent que representa la interfaz de usuario real del cuadro de diálogo. Puede ver que el método render crea una instancia del componente DialogContent de la interfaz de usuario de Fluent, así como de DialogFooter para proporcionar los botones "Cancelar" y "Crear tarea".

Nota:

Puede encontrar más detalles sobre cómo aprovechar Fluent UI Framework; para ello, lea el documento Fluent UI - Get Started (Interfaz de usuario de Fluent: Introducción).

A continuación, el componente de diálogo se define mediante la clase TaskDialog , que hereda del BaseDialog tipo de @microsoft/sp-dialog y acepta dos métodos en su constructor. Estos dos métodos coinciden con las firmas de eventos onSave y onClose y permiten proporcionar a los controladores para implementar la lógica de guardar y cerrar. En el método render del componente TaskDialog , basta con crear una instancia del componente TaskDialogContent .

Por último, pero no menos importante, el componente ShowDialog.tsx React scaffolding en la subcarpeta components del elemento web debe actualizarse en consecuencia a la siguiente implementación.

import * as React from 'react';
import styles from './ShowDialog.module.scss';
import { IShowDialogProps } from './IShowDialogProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PrimaryButton } from '@fluentui/react/lib';

import TaskDialog from './sampleDialog/TaskDialog';

export default class ShowDialog extends React.Component<IShowDialogProps, {}> {
  public render(): React.ReactElement<IShowDialogProps> {
    const {
      isDarkTheme,
      environmentMessage,
      hasTeamsContext,
      userDisplayName
    } = this.props;

    return (
      <section className={`${styles.showDialog} ${hasTeamsContext ? styles.teams : ''}`}>
        <div className={styles.welcome}>
          <img alt="" src={isDarkTheme ? require('../assets/welcome-dark.png') : require('../assets/welcome-light.png')} className={styles.welcomeImage} />
          <h2>Well done, {escape(userDisplayName)}!</h2>
          <div>{environmentMessage}</div>
        </div>
        <div style={{textAlign: 'center', marginTop: '10px'}}>
          <PrimaryButton text='Create Task' onClick={this._createTask} />
        </div>
      </section>
    );
  }

  private _createTask = async (): Promise<void> => {
    const taskDialog = new TaskDialog(
      async (description, dueDate) => {
        alert(`You asked to create the task '${description}' with due date on: ${dueDate}`); },
      async () => alert('You closed the dialog!')
    );
    
    await taskDialog.show();
  }
}

El método render del componente simplemente representa un botón en el centro de la pantalla y al hacer clic en ese botón activa el controlador de _createTask . Internamente, el controlador crea una nueva instancia del taskDialog personalizado, lo que proporciona los controladores de guardar y cancelar al constructor. A continuación, el controlador de _createTask invoca la presentación del método asincrónico del componente de diálogo.

Puede encontrar información adicional sobre este tema leyendo los documentos siguientes: