Cree su primera extensión de tarjeta adaptable de SharePoint

Las extensiones de tarjeta adaptable (ACE) son un nuevo tipo de componente de SharePoint Framework, que permite a los desarrolladores crear extensiones enriquecidas y nativas para los paneles y las páginas de SharePoint de Viva Connections. Dado que las extensiones de tarjeta adaptable usan el marco de tarjeta adaptable de Microsoft para generar la UI con su esquema JSON declarativo, solo tiene que centrarse en la lógica de negocios del componente y dejar que el controlador de SharePoint Framework (SPFx) haga que el componente tenga un buen aspecto y funcione en todas las plataformas.

Importante

En este tutorial se presupone que ha instalado SPFx v1.13. Para obtener más información sobre cómo instalar SPFx versión 1.13, vea SharePoint Framework notas de la versión 1.13.

Aplicar andamiaje a un proyecto de extensión de tarjeta adaptable

Cree un directorio de proyecto nuevo para el proyecto y cambie la carpeta actual a ese directorio.

Cree un nuevo proyecto ejecutando el generador de SharePoint Yeoman desde el nuevo directorio que creó:

yo @microsoft/sharepoint

En el momento en que se le solicite, introduzca los siguientes valores (seleccione la opción predeterminada para todas las solicitudes que se omiten a continuación):

  • ¿Quiere permitir que el administrador del espacio empresarial implemente la solución en todos los sitios inmediatamente sin ejecutar ninguna implementación de características o agregar aplicaciones en sitios?
  • ¿Qué tipo de componente del lado cliente se va a crear? Extensión de tarjeta adaptable
  • ¿Qué plantilla quiere usar? Plantilla de texto principal
  • ¿Cuál es el nombre de la extensión de tarjeta adaptable? HelloWorld
  • ¿Cuál es la descripción de la extensión de tarjeta adaptable? Descripción de HelloWorld

Ahora Yeoman instalará las dependencias necesarias y aplicará el scaffolding a los archivos de solución. Este proceso puede tardar unos minutos.

Actualizar la dirección URL del área de trabajo hospedada del proyecto

Cuando use el servicio de tarea gulp, de forma predeterminada se iniciará un explorador con la dirección URL del área de trabajo hospedada especificada en el proyecto. La dirección URL predeterminada del área de trabajo hospedada en un nuevo proyecto apunta a una dirección URL no válida.

  • Busque y abra el archivo ./config/serve.json en el proyecto.

  • Busque la propiedad initialPage:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
      "port": 4321,
      "https": true,
      "initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
    }
    
  • Cambie el dominio enter-your-SharePoint-site a la dirección URL de su inquilino y sitio de SharePoint que desee usar para las pruebas. Por ejemplo: https://contoso.sharepoint.com/sites/devsite/_layouts/workbench.aspx.

Sugerencia

También puede iniciar el servidor web local sin iniciar un explorador mediante la inclusión del argumento nobrowser en el comando gulp serve. Por ejemplo, es posible que no desee modificar el archivo serve.json en todos los proyectos y, en su lugar, prefiera usar un marcador para iniciar el área de trabajo hospedada.

gulp serve --nobrowser

Servir la ACE en el área de trabajo

Antes de profundizar en el código, ejecute la salida del scaffolding y vea el aspecto de una extensión de tarjeta adaptable.

El bucle de desarrollo interno con las ACE es similar al de los elementos web de SPFx. Podemos crear un servidor localmente y ejecutar el código en el área de trabajo

gulp serve

Una vez que se esté ejecutando el servidor web local, vaya al Workbench hospedado: https://{tenant}.sharepoint.com/_layouts/15/workbench.aspx

Abra el Cuadro de herramientas de elementos web y seleccione su ACE:

Selección de la ACE en el cuadro de herramientas

Explorar la Vista de tarjeta

Las ACE pueden representarse de dos formas distintas. La primera forma de representar una ACE se denomina Vista de tarjeta.

Cuando se representa en un panel o una página, las ACE siempre se iniciarán en esta vista.

ACE representada en la Vista tarjeta

Explorar la Vista rápida

La segunda forma en que una ACE puede representarse se llama Vista rápida. Cuando interactúa con una ACE, las ACE pueden iniciar una experiencia más grande y personalizada.

Nota

La interacción con la ACE se deshabilita mientras está en el modo de Edición. El área de trabajo o la página deben estar en modo de Vista previa o de Lectura para interactuar con la ACE.

Cambie el área de trabajo al modo Vista previa.

Establezca el área de trabajo en el modo de vista previa

Seleccione el botón de Vista Rápida en la ACE:

Seleccione el botón de Vista Rápida en la ACE

Examinar el código al que se le aplicó scaffolding

Explorar la clase base

Busque y abra el siguiente archivo en su proyecto: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts.

export default class HelloWorldAdaptiveCardExtension
  extends BaseAdaptiveCardExtension<IHelloWorldAdaptiveCardExtensionProps,IHelloWorldAdaptiveCardExtensionState> {
  // ...
}

Todas las ACE deben extenderse desde la clase BaseAdaptiveCardExtension. Opcionalmente, puede implementar dos genéricos:

  • TProperties: similar a los elementos web, este es el conjunto de propiedades persistentes del componente (contenedor de propiedades).
  • TState: único para las ACE y puede opcionalmente definir el conjunto de datos representables.

Representación de la ACE

protected renderCard(): string | undefined {
  return CARD_VIEW_REGISTRY_ID;
}

El método renderCard() es virtual que devuelve un identificador de cadena a una vista registrada; más adelante se habla del registro de la Vista. Este método se invoca durante la representación inicial de la Vista de tarjeta.

Si no se sobreescribe renderCard(), entonces se representará una vista de tarjeta de forma predeterminada.

Comente el método renderCard() y vea lo que sucede:

/*
protected renderCard(): string | undefined {
  return CARD_VIEW_REGISTRY_ID;
}
*/

Resultados de comentar el método renderCard()

Quite la marca del método renderCard() para volver al estado original.

La vista de tarjeta predeterminada se representará con las siguientes propiedades del manifiesto:

  • Icono: iconProperty
  • Título: title
  • Texto de la tarjeta: description

Nota

A diferencia de la vista de tarjeta, no hay ninguna vista rápida predeterminada.

Registrar una vista para la ACE

Para usar una vista, debe registrarse con su ViewNavigator correspondiente. Dos ViewNavigator se exponen en la ACE: cardNavigator y quickViewNavigator:

this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView());
this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView());

Nota

Debe registrar una vista antes de poder utilizarla. Puede hacerlo dentro del constructor o método onInit() de la clase.

Vistas de tarjeta

Busque y abra el archivo: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts.

Las vistas de tarjeta deben extenderse desde estas clases base:

  • BaseBasicCardView

    BaseBasicCardView

  • BaseImageCardView

    BaseImageCardView

  • BasePrimaryTextCardView

    BasePrimaryTextCardView

Cada una de estas vistas se representará de forma diferente y tendrá restricciones diferentes sobre los datos que se pueden proporcionar a la plantilla.

Nota

Las vistas de las tarjetas de las plantillas de tarjetas adaptables son fijas y no pueden modificarse.

Además, existen dos genéricos para los objetos properties y state compartidos entre la vista y la ACE.

  • TProperties: la interfaz de propiedades de la vista, la misma interfaz usada por las propiedades persistentes de la ACE (contenedor de propiedades).
  • TState: único para las ACE y puede opcionalmente definir el conjunto de datos representables.

Nota

SPFx propagará automáticamente los cambios del estado de la ACE a cada Vista.

El getter data es el único método que debe ser implementado por una vista de tarjeta. El tipo de valor devuelto es único para la clase padre de la vista.

La propiedad cardButtons determina cuántos botones aparecen en la tarjeta y qué acción realizar al hacer clic en ellos.

Si no se implementa cardButtons, no aparecerá ningún botón en la tarjeta.

Nota

Mientras que la vista de tarjeta inicial se especifica en el método renderCard() de la ACE, la vista rápida inicial se especifica como parte de la acción de un botón parameters. Esto permite que dos botones abran potencialmente diferentes vistas.

Agregue un segundo botón agregando otro objeto a la matriz devuelta por el método cardButtons():

public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] | undefined {
  return [
    {
      title: strings.QuickViewButton,
      action: {
        type: 'QuickView',
        parameters: {
          view: QUICK_VIEW_REGISTRY_ID
        }
      }
    },
    {
      title: 'Bing',
      action: {
        type: 'ExternalLink',
        parameters: {
          target: 'https://www.bing.com'
        }
      }
    }
  ];
}

Inicialmente, no habrá ningún cambio en la tarjeta. Esto se debe a que el tamaño Medio de la tarjeta para BasePrimaryTextCardView solo muestra un botón. SPFx seleccionará el primer elemento de la tupla.

  1. Para cambiar el tamaño de la tarjeta, vaya al panel de propiedades y seleccione Grande.

    Seleccione el tamaño de la tarjeta

    Tarjeta ACE grande representada

  2. Ahora, al seleccionar el botón Bing, Bing se abrirá en una nueva pestaña del explorador.

El método onCardSelection() determina lo que ocurrirá si se hace clic en la tarjeta. Si no se implementa el método onCardSelection(), no ocurrirá nada cuando se haga clic en la tarjeta.

  1. Cambie la selección de la tarjeta para abrir la vista Rápida modificando el método onCardSelection():

    public get onCardSelection(): IQuickViewCardAction | IExternalLinkCardAction | undefined {
      return {
        type: 'QuickView',
        parameters: {
          view: QUICK_VIEW_REGISTRY_ID
        }
      };
    }
    
  2. Ahora, al seleccionar la tarjeta se abrirá la vista rápida.

Vistas rápidas de la ACE

Busque y abra el siguiente archivo: ./src/adaptiveCardExtensions/helloWorld/quickView/QuickView.ts.

Las vistas rápidas deben extender la clase base BaseAdaptiveCardView. Hay tres genéricos opcionales que se pueden definir:

  • TData: el tipo devuelto por el método getter data().
  • TProperties: al igual que la vista tarjeta, se trata de la misma interfaz utilizada por las propiedades persistentes de la ACE (contenedor de propiedades).
  • TState Al igual que la vista de la tarjeta, este es el conjunto de datos de estado que la vista necesita para representar. TState debe compartir propiedades con la interfaz de estado de la ACE.

Una vista rápida tiene más control sobre el esquema de la plantilla de la tarjeta adaptable que una vista de tarjeta. El getter template() debe devolver un JSON válido de la plantilla de la tarjeta adaptable. Las ACEs de SPFx admiten con las plantillas de las tarjetas adaptables. Las propiedades del objeto devuelto por el getter data se asignarán automáticamente a la ranura de la plantilla vinculada.

Por ejemplo, ${description} está vinculado a this.properties.description.

// QuickView.ts
public get data(): IQuickViewData {
  return {
    // ...
    description: this.properties.description
  };
}
// QuickViewTemplate.json.ts
{
  "type": "TextBlock",
  "text": "${description}",
  "wrap": true
}

Nota

Debe usar la sintaxis de enlace de tarjeta adaptable que usa $ y {} corchetes.

Vamos a cambiar esto:

  1. Quite la propiedad description de los datos de vista rápida y agregue dos botones.

  2. Actualice la interfaz IQuickViewData como se muestra en el siguiente código:

    export interface IQuickViewData {
      title: string;
      subTitle: string;
    }
    
  3. Actualice el método data() como se muestra en el siguiente código:

    public get data(): IQuickViewData {
      return {
        subTitle: this.state.subTitle,
        title: strings.Title
      };
    }
    
  4. Busque y abra el siguiente archivo: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts.

  5. Actualice la interfaz IHelloWorldAdaptiveCardExtensionState y el método onInit() de la siguiente manera:

    export interface IHelloWorldAdaptiveCardExtensionState {
      subTitle: string;
    }
    
    ..
    
    public onInit(): Promise<void> {
      this.state = {
        subTitle: 'No button clicked'
      };
      // ...
    }
    

A continuación, quite la referencia a this.properties.description de la vista de tarjeta:

  1. Busque y abra el siguiente archivo: ./src/adaptiveCardExtensions/helloWorld/cardView/CardView.ts.

  2. Quite la propiedad description del objeto devuelto:

    public get data(): IPrimaryTextCardParameters {
      return {
        primaryText: strings.PrimaryText
      };
    }
    

En su getter template(), la vista rápida de la ACE que ha generado devuelve el objeto de un archivo JSON. Modifiquemos esa plantilla:

  1. Busque y abra el siguiente archivo: ./src/adaptiveCardExtensions/helloWorld/quickView/template/QuickViewTemplate.json.

  2. Reemplace el contenido de este archivo por el siguiente JSON:

    {
      "schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "type": "AdaptiveCard",
      "version": "1.2",
      "body": [
        {
          "type": "TextBlock",
          "weight": "Bolder",
          "text": "${title}"
        },
        {
          "type": "TextBlock",
          "text": "${subTitle}",
          "wrap": true
        },
        {
          "type": "ActionSet",
          "actions": [
            {
              "type": "Action.Submit",
              "title": "Button One",
              "style": "positive",
              "data": {
                "id": "button1",
                "message": "Clicked Button One"
              }
            },
            {
              "type": "Action.Submit",
              "title": "Button Two",
              "data": {
                "id": "button2",
                "message": "Clicked Button Two"
              }
            }
          ]
        }
      ]
    }
    

Pruebe los cambios actualizando el área de trabajo hospedada en el explorador. Debería recoger los cambios que haya aplicado al proyecto si gulp serve sigue ejecutándose:

Vista rápida de ACE actualizada

Sugerencia

Obtenga más información sobre las tarjetas adaptables en https://adaptivecards.io. Este sitio también incluye un Diseñador de tarjetas adaptables que le permite obtener una vista previa de la representación y la estructura de las tarjetas adaptables a medida que las creas.

En este momento, ha modificado la ACE para incluir dos botones nuevos en la tarjeta de vista rápida. El siguiente paso es implementar lo que sucede cuando se seleccionan estos botones. Esto se realiza mediante controladores de acción.

Controladores de acciones

Las acciones son controladas por las vistas en las que están definidas.

La vista rápida tiene dos botones, pero la vista no controla actualmente la acción Enviar. El método onAction() se invoca siempre que se ejecuta una acción de tarjeta adaptable, por ejemplo, cuando se inicia la acción Action.Submit.

Busque y abra el archivo QuickView.ts y sobreescriba onAction() para controlar las dos selecciones de botón, como se muestra en el siguiente código:

import { ISPFxAdaptiveCard, BaseAdaptiveCardView, IActionArguments } from '@microsoft/sp-adaptive-card-extension-base';

..

public onAction(action: IActionArguments): void {
  if (action.type === 'Submit') {
    const { id, message } = action.data;
    switch (id) {
      case 'button1':
      case 'button2':
        this.setState({
          subTitle: message
        });
        break;
    }
  }
}

Pruebe los cambios actualizando el área de trabajo hospedada en el explorador. Debe recoger los cambios que haya aplicado al proyecto si gulp serve todavía se está ejecutando.

Al seleccionar cualquiera de los botones, el estado de subTitle se establecerá con valor data.message, lo que provocará una nueva representación (más adelante se hablará de esto). La tarjeta adaptable de la vista rápida mostrará ahora este mensaje, ya que su plantilla se vincula a subTitle.

Panel de propiedades

Al igual que los elementos web, las ACE pueden tener propiedades configurables que los usuarios establecen con los permisos adecuados. Esto le permite personalizar cada implementación de la ACE. Esto se realiza mediante el panel de propiedades.

Las ACE se pueden configurar igual que los elementos web. Las firmas API son idénticas para los métodos siguientes, que se encuentran en el archivo HelloWorldAdaptiveCardExtension.ts:

  • getPropertyPaneConfiguration()
  • onPropertyPaneFieldChanged()

El scaffolding predeterminado para las ACE usa una nueva API que tiene como objetivo minimizar el tamaño del paquete cuando el componente no está en el modo de Edición. El método loadPropertyPaneResources() usa la característica de fragmentación de Webpack para separar el código específico del panel de propiedades en su propio archivo JS, que se puede cargar a petición.

Además de devolver la configuración del panel de propiedades, la clase HelloWorldPropertyPane se usa para encapsular toda su lógica del modo de Edición.

Propiedades

Aparte del campo Tamaño de tarjeta, la ACE a la que se aplicó scaffolding tiene tres (3) campos configurables que se definen en el método getPropertyPaneConfiguration() y en la interfaz IHelloWorldAdaptiveCardExtension:

  • title
  • iconProperty
  • description

Las vistas de tarjeta están diseñadas para funcionar automáticamente en todos los tamaños de tarjeta. Además de especificar un tamaño de tarjeta predeterminado, las ACE no pueden controlar esta propiedad.

Las propiedades title y iconProperty, definidas en el archivo de ACE (por ejemplo, HelloWorldAdaptiveCardExtension.ts) se usan en las ACE getter title() y iconProperty(), respectivamente, para configurar el título y el icono de la tarjeta:

El valor title se usa en el título del panel de propiedades y en el título que se muestra en la tarjeta.

public get title(): string {
  return this.properties.title;
}

El valor iconProperty es la dirección URL del icono que usan las vistas de tarjeta.

protected get iconProperty(): string {
  return this.properties.iconProperty || require('./assets/sharepointlogo.png');
}

Estado

La propiedad state debe inicializarse antes de llamar al método setState() y solo se puede inicializar una vez.

public onInit(): Promise<void> {
  this.state = {
    subTitle: 'No button clicked'
  };
  // ...
}

A diferencia del valor properties, state no se conserva después de la sesión actual y solo se debe usar para el estado de vista efímera.

Nota

La ACE scaffolded mantiene una propiedad description en el objeto state. Esto está obsoleto, ya que la ACE y todas sus vistas simplemente pueden hacer referencia al valor description almacenado en properties.

Volviendo a representar...

El proceso de volver a representar se produce cuando se actualiza una propiedad en el panel de propiedades o si se llama a setState().

Al actualizar el valor del campo Descripción del panel de propiedades, se actualizará la descripción en la tarjeta. Veamos cómo hacerlo:

  1. Busque y abra el siguiente archivo: ./src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts.

  2. Como ejemplo trivial, actualice el valor de subTitle cuando el valor description se actualice durante el evento onPropertyPaneFieldChanged. Agregue el siguiente código a la clase HELLOWorldAdaptiveCardExtension de la ACE:

    protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
      if (propertyPath === 'description') {
        this.setState({
          subTitle: newValue
        });
      }
    }
    

Al pasar un objeto Partial<TState> a un método setState() se actualizarán todas las vistas con los nuevos valores. Al actualizar el campo Descripción en el panel de propiedades, se actualizará el valor subTitle que se muestra en la vista rápida.

Si no se pasa ningún valor o valores idénticos, se producirá igualmente una nueva representación.

El método setState() no se limita solo al panel de propiedades. Se puede usar en respuesta a la recepción de nuevos datos o como resultado de alguna acción del usuario.

Conclusión

Después de este tutorial, debería estar familiarizado con:

  • Aplicar scaffolding a una extensión de tarjeta adaptable
  • Registrar vistas
  • Cambiar la vista de tarjeta y la vista rápida
  • Control de acciones básicas
  • Cambiar el panel de propiedades
  • Aplazar la carga del panel de propiedades
  • Cómo usar state
  • Diferencia entre properties y state