Compartir a través de


Migrar de UserCustomAction a Extensiones de SharePoint Framework

Muchas soluciones empresariales basadas en Microsoft 365 y SharePoint Online aprovecharon la funcionalidad CustomAction del sitio de SharePoint Feature Framework para ampliar la interfaz de usuario de las páginas. En la interfaz de usuario "moderna" actual de SharePoint Server 2019 y SharePoint Online, la mayoría de esas personalizaciones ya no están disponibles. Afortunadamente, con extensiones de SharePoint Framework, puede proporcionar una funcionalidad similar en la interfaz de usuario "moderna".

En este tutorial, obtendrá información sobre cómo migrar de las anteriores personalizaciones "clásicas" al nuevo modelo basado en extensiones de SharePoint Framework.

En primer lugar, se presentan las opciones disponibles al desarrollar extensiones de SharePoint Framework:

La opción más útil en este contexto es la extensión Application Customizer.

Supongamos que tiene customAction en SharePoint Online para tener un pie de página personalizado en todas las páginas del sitio.

En el siguiente fragmento de código, puede ver el código XML que define ese evento CustomAction con el marco de características de SharePoint.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="jQueryCDN"
                Title="jQueryCDN"
                Description="Loads jQuery from the public CDN"
                ScriptSrc="https://code.jquery.com/jquery-3.2.1.slim.min.js"
                Location="ScriptLink"
                Sequence="100" />
  <CustomAction Id="spoCustomBar"
                Title="spoCustomBar"
                Description="Loads a script to rendere a custom footer"
                Location="ScriptLink"
                ScriptSrc="SiteAssets/SPOCustomUI.js"
                Sequence="200" />
</Elements>

Como puede ver, el archivo de elementos de la característica define algunos elementos de tipo CustomAction para incluir en las páginas del sitio de destino: jQuery, cargadas a través de la red CDN pública, y un archivo personalizado de JavaScript que representa el pie de página personalizado.

Por razones de integridad, puede ver el código JavaScript que representa un pie de página personalizado, cuyos elementos de menú se definen previamente en el código por simplificar.

var SPOCustomUI = SPOCustomUI || {};

SPOCustomUI.setUpCustomFooter = function () {
  if ($("#SPOCustomFooter").length)
    return;

  var footerContainer = $("<div>");
  footerContainer.attr("id", "SPOCustomFooter");

  footerContainer.append("<ul>");

  $("#s4-workspace").append(footerContainer);
}

SPOCustomUI.addCustomFooterText = function (id, text) {
  if ($("#" + id).length)
    return;

  var customElement = $("<div>");
  customElement.attr("id", id);
  customElement.html(text);

  $("#SPOCustomFooter > ul").before(customElement);

  return customElement;
}

SPOCustomUI.addCustomFooterLink = function (id, text, url) {
  if ($("#" + id).length)
    return;

  var customElement = $("<a>");
  customElement.attr("id", id);
  customElement.attr("href", url);
  customElement.html(text);

  $("#SPOCustomFooter > ul").append($("<li>").append(customElement));

  return customElement;
}

SPOCustomUI.loadCSS = function (url) {
  var head = document.getElementsByTagName('head')[0];
  var style = document.createElement('link');
  style.type = 'text/css';
  style.rel = 'stylesheet';
  style.href = url;
  head.appendChild(style);
}

SPOCustomUI.init = function (whenReadyDoFunc) {
  // avoid executing inside iframes (used by SharePoint for dialogs)
  if (self !== top) return;

  if (!window.jQuery) {
    // jQuery is needed for Custom Bar to run
    setTimeout(function () { SPOCustomUI.init(whenReadyDoFunc); }, 50);
  } else {
    $(function () {
      SPOCustomUI.setUpCustomFooter();
      whenReadyDoFunc();
    });
  }
}

// The following initializes the custom footer with some fake links
SPOCustomUI.init(function () {
  var currentScriptUrl;

  var currentScript = document.querySelectorAll("script[src*='SPOCustomUI']");
  if (currentScript.length > 0) {
    currentScriptUrl = currentScript[0].src;
  }
  if (currentScriptUrl != undefined) {
    var currentScriptBaseUrl = currentScriptUrl.substring(0, currentScriptUrl.lastIndexOf('/') + 1);
    SPOCustomUI.loadCSS(currentScriptBaseUrl + 'SPOCustomUI.css');
  }

  SPOCustomUI.addCustomFooterText('SPOFooterCopyright', '&copy; 2017, Contoso Inc.');
  SPOCustomUI.addCustomFooterLink('SPOFooterCRMLink', 'CRM', 'CRM.aspx');
  SPOCustomUI.addCustomFooterLink('SPOFooterSearchLink', 'Search Center', 'SearchCenter.aspx');
  SPOCustomUI.addCustomFooterLink('SPOFooterPrivacyLink', 'Privacy Policy', 'Privacy.aspx');
});

En la siguiente ilustración, puede ver el resultado de la acción personalizada anterior en la página principal de un sitio clásico.

Pie de página personalizado en una página clásica

Para migrar la solución anterior a la interfaz de usuario "moderna", vea los siguientes pasos.

Crear una solución nueva de SharePoint Framework

  1. Desde la consola, cree una carpeta para el proyecto:

    md spfx-react-custom-footer
    
  2. Vaya a la carpeta del proyecto:

    cd spfx-react-custom-footer
    
  3. En la carpeta del proyecto, ejecute el generador de Yeoman de SharePoint Framework para aplicar scaffolding a un nuevo proyecto de SharePoint Framework:

    yo @microsoft/sharepoint
    
  4. En el momento en que se le solicite, introduzca los siguientes valores (seleccione la opción predeterminada para todas las solicitudes que se omitan a continuación):

    • ¿Cuál es el nombre de la solución?: spfx-react-custom-footer
    • ¿Qué paquetes de línea base quiere usar como destino para el componente o los componentes?: solo SharePoint Online (versión más reciente)
    • ¿Cuál es el tipo de componente del lado cliente que se va a crear?: Extensión
    • ¿Qué tipo de extensión del lado cliente se va a crear? Personalizador de aplicación
    • ¿Cuál es el nombre del personalizador de campo? CustomFooter

    En este momento, Yeoman instalará las dependencias requeridas y aplicará scaffolding a los archivos y las carpetas de la solución con la extensión CustomFooter. Esta operación puede tardar unos minutos.

  5. Inicie Visual Studio Code (o el editor de código que prefiera) y empiece a desarrollar la solución. Para iniciar Visual Studio Code, puede ejecutar la siguiente instrucción.

    code .
    

Definir los elementos de la nueva interfaz de usuario

Los elementos de la interfaz de usuario del pie de página personalizado se representan con React y un componente de React personalizado. Puede crear los elementos de la interfaz de usuario del pie de página de ejemplo con la tecnología que quiera. En este tutorial, se usa React para aprovechar los componentes de Office UI Fabric para React.

  1. Abra la carpeta ./src/extensions/customFooter/CustomFooterApplicationCustomizer.manifest.json del archivo. Copie el valor de la propiedad id y guárdelo en un lugar seguro, ya que lo necesitará más adelante.

  2. Abra el archivo ./src/extensions/customFooter/CustomFooterApplicationCustomizer.ts e importe los tipos PlaceholderContent y PlaceholderName desde el paquete @microsoft/sp-application-base.

    Y, al principio del archivo, agregue las import directivas para React.

    Puede ver la sección de importaciones del archivo CustomFooterApplicationCustomizer.ts en el siguiente fragmento de código.

    import * as React from 'react';
    import * as ReactDom from 'react-dom';
    
    import { override } from '@microsoft/decorators';
    import { Log } from '@microsoft/sp-core-library';
    import {
      BaseApplicationCustomizer,
      PlaceholderContent,
      PlaceholderName
    } from '@microsoft/sp-application-base';
    import { Dialog } from '@microsoft/sp-dialog';
    
    import * as strings from 'CustomFooterApplicationCustomizerStrings';
    import CustomFooter from './components/CustomFooter';
    
  3. Busque la definición de la clase CustomFooterApplicationCustomizer y declare un nuevo miembro privado denominado bottomPlaceholder de tipo PlaceholderContent | undefined.

  4. En la invalidación del método onInit(), invoque una función personalizada denominada renderPlaceHolders y defina esa función.

    En el fragmento de código siguiente, puede ver la implementación de la clase Application Customizer de pie de página personalizada.

    /** A Custom Action which can be run during execution of a Client Side Application */
    export default class CustomFooterApplicationCustomizer
    extends BaseApplicationCustomizer<ICustomFooterApplicationCustomizerProperties> {
    
      // This private member holds a reference to the page's footer
      private _bottomPlaceholder: PlaceholderContent | undefined;
    
      @override
      public onInit(): Promise<void> {
        Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
    
        let message: string = this.properties.testMessage;
        if (!message) {
          message = '(No properties were provided.)';
        }
    
        // Call render method for rendering the needed html elements
        this._renderPlaceHolders();
    
        return Promise.resolve();
      }
    
      private _renderPlaceHolders(): void {
    
        // Handling the bottom placeholder
        if (!this._bottomPlaceholder) {
          this._bottomPlaceholder =
            this.context.placeholderProvider.tryCreateContent(PlaceholderName.Bottom);
    
          // The extension should not assume that the expected placeholder is available.
          if (!this._bottomPlaceholder) {
            console.error('The expected placeholder (Bottom) was not found.');
            return;
          }
    
          const element: React.ReactElement<{}> = React.createElement(CustomFooter);
    
          ReactDom.render(element, this._bottomPlaceholder.domElement);
        }
      }
    }
    

    El método renderPlaceHolders() busca el marcador de posición de tipo Bottom y, si lo hay, representa su contenido. De hecho, al final del renderPlaceHolders() método, el código crea una nueva instancia de un CustomFooter componente React y lo representa dentro del marcador de posición de la parte inferior de las páginas (es decir, donde se debe representar el pie de página).

    Nota:

    El componente de React será el reemplazo, en la interfaz de usuario "moderna", del archivo JavaScript del modelo "clásico". Por supuesto, todavía puede representar todo el pie de página con código JavaScript puro y reutilizando la mayor parte del código que ya tiene. No obstante, se recomienda considerar la posibilidad de actualizar la implementación no solo desde la perspectiva tecnológica, sino también desde la perspectiva del código.

  5. Agregue una nueva carpeta denominada components en la carpeta src/extensions/customFooter .

  6. Cree un archivo en la nueva carpeta y denomínelo CustomFooter.tsx.

    Agregue el código siguiente a este archivo:

    import * as React from 'react';
    import { CommandButton } from 'office-ui-fabric-react/lib/Button';
    
    export default class CustomFooter extends React.Component<{}, {}> {
      public render(): React.ReactElement<{}> {
        return (
          <div className={`ms-bgColor-neutralLighter ms-fontColor-white`}>
            <div className={`ms-bgColor-neutralLighter ms-fontColor-white`}>
              <div className={`ms-Grid`}>
                <div className="ms-Grid-row">
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                        data-automation="CopyRight"
                        href={`CRM.aspx`}>&copy; 2017, Contoso Inc.</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                            data-automation="CRM"
                            iconProps={ { iconName: 'People' } }
                            href={`CRM.aspx`}>CRM</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                            data-automation="SearchCenter"
                            iconProps={ { iconName: 'Search' } }
                            href={`SearchCenter.aspx`}>Search Center</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                        data-automation="Privacy"
                        iconProps={ { iconName: 'Lock' } }
                        href={`Privacy.aspx`}>Privacy Policy</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm4 ms-md4 ms-lg4"></div>
                </div>
              </div>
            </div>
          </div>
        );
      }
    }
    

    Enseñarle a escribir un componente de React queda fuera del ámbito de este documento. Observe las import instrucciones al principio, donde el componente importa React y el CommandButton componente React de la biblioteca de componentes de Office UI Fabric.

    En el método render() del componente, se define el resultado del CustomFooter con varias instancias del componente CommandButton para los vínculos del pie de página. Todo el resultado HTML se ajusta en un diseño de cuadrícula de Office UI Fabric.

    Nota:

    Para más información sobre el diseño de cuadrícula de Office UI Fabric, vea Diseño dinámico.

    Puede ver el resultado en la siguiente ilustración.

    Pie de página personalizado representado en un sitio

Probar la solución en modo de depuración

  1. Volver a la ventana de la consola y ejecutar el siguiente comando para compilar la solución y ejecutar el servidor local Node.js para hospedarlo.

    gulp serve --nobrowser
    
  2. Abra ahora su explorador favorito y vaya a una página "moderna" de un sitio de grupo "moderno". Ahora, anexe los siguientes parámetros de cadena de consulta a la dirección URL de la página.

    ?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"82242bbb-f951-4c71-a978-80eb8f35e4c1":{"location":"ClientSideExtension.ApplicationCustomizer"}}
    

    En esta cadena de consulta, reemplace el GUID por el valor de id que ha guardado en el archivo CustomFooterApplicationCustomizer.manifest.json.

    Tenga en cuenta que al ejecutar la solicitud de página, se le pedirá un cuadro de mensaje de advertencia con el título "Permitir scripts de depuración?", que le pide su consentimiento para ejecutar código desde localhost por motivos de seguridad. Si desea depurar y probar localmente la solución, tiene que permitir que "Cargar scripts de depuración".

    Nota:

    Como alternativa, puede crear entradas de configuración de servidor en el archivo config/serve.json del proyecto para automatizar la creación de los parámetros de cadena de consulta de depuración como se describe en este documento: Depurar soluciones de SharePoint Framework en páginas modernas de SharePoint

Empaquetar y hospedar la solución

Si le gusta el resultado, ya puede empaquetar la solución y hospedarla en una infraestructura de hospedaje real.

Antes de crear la agrupación y el paquete, deberá declarar un archivo XML de Feature Framework para aprovisionar la extensión.

Revisar los elementos de Feature Framework

  1. En el editor de código, abra el archivo /sharepoint/assets/elements.xml. Puede ver el aspecto que debe tener el archivo en el siguiente fragmento de código.

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <CustomAction
          Title="CustomFooter"
          Location="ClientSideExtension.ApplicationCustomizer"
          ClientSideComponentId="82242bbb-f951-4c71-a978-80eb8f35e4c1">
      </CustomAction>
    </Elements>
    

    Como puede ver, recuerda al archivo del marco de características de SharePoint que se ha visto en el modelo "clásico", pero usa el atributo ClientSideComponentId para hacer referencia a id de la extensión personalizada. También puede agregar un ClientSideComponentProperties atributo si necesita proporcionar una configuración personalizada a la extensión, que no es el caso en este tutorial.

  2. Abra la carpeta ./config/package-solution.json del archivo de la solución. Dentro del archivo, puede ver que hay una referencia al archivo elements.xml dentro de la assets sección .

    {
      "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
      "solution": {
        "name": "spfx-react-custom-footer-client-side-solution",
        "id": "911728a5-7bde-4453-97b2-2eba59277ed3",
        "version": "1.0.0.0",
        "features": [
        {
          "title": "Application Extension - Deployment of custom action.",
          "description": "Deploys a custom action with ClientSideComponentId association",
          "id": "f16a2612-3163-46ad-9664-3d3daac68cff",
          "version": "1.0.0.0",
          "assets": {
            "elementManifests": [
              "elements.xml"
            ]
          }
        }]
      },
      "paths": {
        "zippedPackage": "solution/spfx-react-custom-footer.sppkg"
      }
    }
    

Agrupación, empaquetado e implementación de la solución

Después debe empaquetar el paquete de soluciones en el catálogo de aplicaciones. Para realizar esta tarea, siga estos pasos.

Prepare e implemente la solución para el espacio empresarial de SharePoint Online:

  1. Ejecute la tarea siguiente para agrupar la solución. Esto crea una compilación de versión del proyecto:

    gulp bundle --ship
    
  2. Ejecute la siguiente tarea para empaquetar la solución. Este comando crea un paquete *.sppkg en la carpeta sharepoint/solution .

    gulp package-solution --ship
    
  3. En el Catálogo de aplicaciones del espacio empresarial, cargue (o arrastre y coloque) el nuevo paquete de solución del lado cliente y, después, seleccione el botón Implementar.

Instalar y ejecutar la solución

  1. Abra el explorador y navegue a cualquier sitio de destino "moderno".

  2. Vaya a la página Contenidos del sitio y seleccione agregar una nueva Aplicación.

  3. Seleccione esta opción para instalar una nueva aplicación De su organización para examinar las soluciones disponibles en el Catálogo de aplicaciones.

  4. Seleccione la solución denominada spfx-react-custom-footer-client-side-solution e instálela en el sitio de destino.

    Agregar una interfaz de usuario de aplicación para agregar la solución a un sitio

  5. Cuando se haya completado la instalación de la aplicación, actualice la página o vaya a la página principal del sitio. Debería ver el pie de página personalizado en acción.

¡Disfruta de tu nuevo pie de página personalizado creado con las extensiones de SharePoint Framework!

Vea también