Compartir a través de


Migrar una solución de jQuery y DataTables creada con el elemento webScript Editor a SharePoint Framework

Uno de los complementos de jQuery usados con frecuencia es DataTables. Con DataTables, puede crear fácilmente información general de datos eficaces de los datos procedentes de SharePoint y api externas.

Lista de solicitudes de TI creadas con el elemento web Script Editor

Para mostrar el proceso de migración de una personalización de SharePoint con DataTables a SharePoint Framework, use la siguiente solución que muestra información general de solicitudes de soporte técnico de TI recuperadas de una lista de SharePoint.

Información general de solicitudes de soporte técnico de TI mostrada en una página de SharePoint

La solución se crea con el elemento web Editor de scripts de SharePoint estándar. La personalización usa el código siguiente:

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.js"></script>
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
<table id="requests" class="display" cellspacing="0" width="100%">
  <thead>
    <tr>
      <th>ID</th>
      <th>Business unit</th>
      <th>Category</th>
      <th>Status</th>
      <th>Due date</th>
      <th>Assigned to</th>
    </tr>
  </thead>
</table>
<script>
  // UMD
  (function(factory) {
    "use strict";

    if (typeof define === 'function' && define.amd) {
      // AMD
      define(['jquery'], function ($) {
        return factory( $, window, document );
      });
    }
    else if (typeof exports === 'object') {
      // CommonJS
      module.exports = function (root, $) {
        if (!root) {
          root = window;
        }

        if (!$) {
          $ = typeof window !== 'undefined'
            ? require('jquery')
            : require('jquery')( root );
        }

        return factory($, root, root.document);
      };
    } else {
      // Browser
      factory(jQuery, window, document);
    }
  }
  (function($, window, document) {
    $.fn.dataTable.render.moment = function (from, to, locale) {
      // Argument shifting
      if (arguments.length === 1) {
        locale = 'en';
        to = from;
        from = 'YYYY-MM-DD';
      } else if (arguments.length === 2) {
        locale = 'en';
      }

      return function (d, type, row) {
        var m = window.moment(d, from, locale, true);

        // Order and type get a number value from Moment, everything else
          // sees the rendered value
          return m.format(type === 'sort' || type === 'type' ? 'x' : to);
        };
      };
    }));
</script>
<script>
$(document).ready(function() {
  $('#requests').DataTable({
    'ajax': {
      'url': "../_api/web/lists/getbytitle('IT Requests')/items?$select=ID,BusinessUnit,Category,Status,DueDate,AssignedTo/Title&$expand=AssignedTo/Title",
      'headers': { 'Accept': 'application/json;odata=nometadata' },
      'dataSrc': function(data) {
        return data.value.map(function(item) {
          return [
            item.ID,
            item.BusinessUnit,
            item.Category,
            item.Status,
            new Date(item.DueDate),
            item.AssignedTo.Title
          ];
        });
      }
    },
    columnDefs: [{
      targets: 4,
      render: $.fn.dataTable.render.moment('YYYY/MM/DD')
    }]
  });
});
</script>

En primer lugar, la personalización carga las bibliotecas que usa: jQuery, DataTables y Moment.js.

Luego, especifica la estructura de la tabla que se usa para presentar los datos.

Después de crear la tabla, encapsula Moment.js en un complemento DataTables para que puedan formatearse las fechas mostradas en la tabla.

Por último, la personalización usa DataTables para cargar y presentar la lista de solicitudes de soporte técnico de TI. Los datos se cargan mediante AJAX desde una lista de SharePoint.

Gracias al uso de DataTables, los usuarios finales obtienen una solución eficaz en la que pueden filtrar, ordenar y recorrer los resultados en la página sin ningún esfuerzo de desarrollo adicional.

Lista de solicitudes de soporte técnico de TI mostrada con DataTables y filtrada por solicitudes asignadas a Lidia en orden descendente por fecha de vencimiento

Migrar la solución de resúmenes de solicitudes de TI del elemento web Script Editor a SharePoint Framework

La transformación de esta personalización en SharePoint Framework ofrece varias ventajas, como una configuración más sencilla y la administración centralizada de la solución. Seguidamente se ofrece una descripción paso a paso de cómo se migraría la solución a SharePoint Framework. En primer lugar, migrará la solución a SharePoint Framework con el menor número de cambios posibles en el código original. Más adelante, transformará el código de la solución a TypeScript para aprovechar sus características de seguridad de tipos en tiempo de desarrollo.

Nota:

El código fuente del proyecto en las distintas fases de migración está disponible en Tutorial: Migrar la solución de jQuery y DataTables compilada con el elemento web Script Editor a SharePoint Framework.

Crear un proyecto de SharePoint Framework

  1. Empiece por crear una carpeta para el proyecto:

    md datatables-itrequests
    
  2. Vaya a la carpeta del proyecto:

    cd datatables-itrequests
    
  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):

    • ¿Cómo se llama su solución?: datatables-itrequests
    • ¿Cuál es el tipo de componente del lado cliente que se va a crear?: Elemento web
    • ¿Cómo se llama su elemento web?: Solicitudes de TI
    • ¿Cuál es la descripción del elemento web?: Muestra información general de las solicitudes de soporte técnico de TI
    • ¿Qué marco desearía usar?: sin marco de JavaScript
  5. Abra la carpeta del proyecto en el editor de código. En este tutorial, usará Visual Studio Code:

Cargar bibliotecas de JavaScript

Similar to the original solution built using the Script Editor web part, first you need to load the JavaScript libraries required by the solution. In SharePoint Framework this usually consists of two steps: specifying the URL from which the library should be loaded, and referencing the library in the code.

  1. Especifique las direcciones URL desde las que deben cargarse las bibliotecas. En el editor de código, abra el archivo ./config/config.json y cambie la sección externals a:

    {
      // ..
      "externals": {
        "jquery": {
          "path": "https://code.jquery.com/jquery-1.12.4.min.js",
          "globalName": "jQuery"
        },
        "datatables.net": {
          "path": "https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js",
          "globalName": "jQuery",
          "globalDependencies": [
            "jquery"
          ]
        },
        "moment": "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"
      },
      // ..
    }
    

    Esto sirve para dos propósitos:

    1. Cuando la cadena de herramientas de compilación de SharePoint Framework crea el paquete del elemento web, pasará por alto cualquier instrucción import o require para estos tres paquetes y no incluirá el origen en el paquete. Sin estos elementos, WebPack (la herramienta usada para crear el paquete) importaría estas bibliotecas de JavaScript en el paquete resultante de componentes de SPFx.
    2. La cadena de herramientas de compilación de SharePoint Framework agregará estos tres paquetes como dependencias en el manifiesto del componente. Esto indica al cargador de módulos de SharePoint Framework que debe asegurarse de que estas bibliotecas se hayan cargado en la página antes de cargar el paquete del componente.

    Nota:

    Para más información sobre cómo hacer referencia a bibliotecas externas en proyectos de SharePoint Framework, consulte Agregar una biblioteca externa al elemento web del lado cliente de SharePoint.

  2. Abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y, tras la última instrucción import, agregue:

    import 'jquery';
    import 'datatables.net';
    import 'moment';
    

Definir la tabla de datos

Al igual que en la solución original, el paso siguiente consiste en definir la estructura de la tabla usada para mostrar los datos.

En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y cambie el método render() por:

export default class ItRequestsWebPart extends BaseClientSideWebPart<IItRequestsWebPartProps> {
  public render(): void {
    this.domElement.innerHTML = `
      <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
      <table id="requests" class="display ${styles.itRequests}" cellspacing="0" width="100%">
        <thead>
          <tr>
            <th>ID</th>
            <th>Business unit</th>
            <th>Category</th>
            <th>Status</th>
            <th>Due date</th>
            <th>Assigned to</th>
          </tr>
        </thead>
      </table>`;
  }
  // ...
}

Registrar el complemento Moment.js para DataTables

El siguiente paso consiste en definir el complemento Moment.js para DataTables para que pueda darse formato a las fechas de la tabla.

  1. En la carpeta ./src/webparts/itRequests, cree un archivo denominado moment-plugin.js y pegue el código siguiente:

    // UMD
    (
      function (factory) {
        "use strict";
    
        if (typeof define === 'function' && define.amd) {
          // AMD
          define(['jquery'], function ($) {
            return factory($, window, document);
          });
        } else if (typeof exports === 'object') {
          // CommonJS
          module.exports = function (root, $) {
            if (!root) {
              root = window;
            }
    
            if (!$) {
              $ = typeof window !== 'undefined'
                ? require('jquery')
                : require('jquery')(root);
            }
    
            return factory($, root, root.document);
          };
        } else {
          // Browser
          factory(jQuery, window, document);
        }
      }
    
      (function ($, window, document) {
        $.fn.dataTable.render.moment = function (from, to, locale) {
          // Argument shifting
          if (arguments.length === 1) {
            locale = 'en';
            to = from;
            from = 'YYYY-MM-DD';
          } else if (arguments.length === 2) {
            locale = 'en';
          }
    
          return function (d, type, row) {
            var moment = require('moment');
            var m = moment(d, from, locale, true);
    
            // Order and type get a number value from Moment, everything else
            // sees the rendered value
            return m.format(type === 'sort' || type === 'type' ? 'x' : to);
          };
        };
      })
    );
    
  2. Para que el elemento web cargue el complemento, tiene que hacer referencia al archivo moment-plugin.js recién creado. En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y, tras la última instrucción import, agregue:

    import './moment-plugin';
    

Inicializar DataTables y cargar los datos

El último paso consiste en incluir el código que inicializa la tabla de datos y carga los datos de SharePoint.

  1. En la carpeta ./src/webparts/itRequests, cree un archivo denominado script.js y pegue el código siguiente:

    $(document).ready(function () {
      $('#requests').DataTable({
        'ajax': {
          'url': "../../_api/web/lists/getbytitle('IT Requests')/items?$select=ID,BusinessUnit,Category,Status,DueDate,AssignedTo/Title&$expand=AssignedTo/Title",
          'headers': { 'Accept': 'application/json;odata=nometadata' },
          'dataSrc': function (data) {
            return data.value.map(function (item) {
              return [
                item.ID,
                item.BusinessUnit,
                item.Category,
                item.Status,
                new Date(item.DueDate),
                item.AssignedTo.Title
              ];
            });
          }
        },
        columnDefs: [{
          targets: 4,
          render: $.fn.dataTable.render.moment('YYYY/MM/DD')
        }]
      });
    });
    

Nota:

Asegúrese de usar el nombre interno (o nombre estático) de las columnas en los parámetros $select y $expend.

  1. Para hacer referencia a este archivo en el elemento web, en el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y agregue require('./script'); al final del método render(). El método render() debería tener la siguiente apariencia:

    export default class ItRequestsWebPart extends BaseClientSideWebPart<IItRequestsWebPartProps> {
      public render(): void {
        this.domElement.innerHTML = `
          <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
          <table id="requests" class="display ${styles.itRequests}" cellspacing="0" width="100%">
            <thead>
              <tr>
                <th>ID</th>
                <th>Business unit</th>
                <th>Category</th>
                <th>Status</th>
                <th>Due date</th>
                <th>Assigned to</th>
              </tr>
            </thead>
          </table>`;
    
        require('./script');
      }
      // ...
    }
    
  2. Compruebe que el elemento web funciona del modo previsto. Para ello, ejecute lo siguiente en la línea de comandos:

    gulp serve --nobrowser
    

Dado que el elemento web carga sus datos de SharePoint, tiene que probar el elemento web con el SharePoint Framework Workbench hospedado. Desplácese hasta https://{nombre-de-su-espacio-empresarial}.sharepoint.com/_layouts/workbench.aspx y agregue el elemento web al lienzo. Ahora debería ver las solicitudes de TI mostradas con el complemento DataTables de jQuery.

Solicitudes de TI mostradas en un elemento web del lado cliente de SharePoint Framework

Agregar compatibilidad con la configuración del elemento web mediante las propiedades de elemento web

En los pasos anteriores, migró las soluciones de solicitudes de TI del elemento web Editor de scripts al SharePoint Framework. Aunque la solución ya funciona según lo previsto, no usa ninguna de las ventajas SharePoint Framework. El nombre de la lista desde la que se cargan las solicitudes de TI se incluye en el código y el propio código es JavaScript sin formato, que es más difícil de refactorizar que TypeScript.

En los pasos siguientes se muestra cómo ampliar la solución existente para permitir a los usuarios especificar el nombre de la lista desde la que cargar los datos. Más adelante, transformará el código en TypeScript para beneficiarse de sus características de seguridad de tipos.

Definir la propiedad del elemento web para almacenar el nombre de la lista

  1. Defina una propiedad del elemento web para almacenar el nombre de la lista desde la que deben cargarse las solicitudes de TI. En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.manifest.json, cambie el nombre de la propiedad description predeterminada a listName y borre el valor.

    Propiedad listName del manifiesto del elemento web resaltada en Visual Studio Code

  2. Actualice la interfaz de propiedades del elemento web para reflejar los cambios en el manifiesto. En el editor de código, abra el archivo ./src/webparts/itRequests/IItRequestsWebPartProps.ts y cambie su contenido a:

    export interface IItRequestsWebPartProps {
      listName: string;
    }
    
  3. Actualice las etiquetas de visualización de la propiedad listName. Abra el archivo ./src/webparts/itRequests/loc/mystrings.d.ts y cambie el contenido a:

    declare interface IItRequestsStrings {
      PropertyPaneDescription: string;
      BasicGroupName: string;
      ListNameFieldLabel: string;
    }
    
    declare module 'itRequestsStrings' {
      const strings: IItRequestsStrings;
      export = strings;
    }
    
  4. Abra el archivo ./src/webparts/itRequests/loc/en-us.js y cambie el contenido a:

    define([], function() {
      return {
        "PropertyPaneDescription": "IT Requests settings",
        "BasicGroupName": "Data",
        "ListNameFieldLabel": "List name"
      }
    });
    
  5. Actualice el elemento web para que use la propiedad recién definida. En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y cambie el método getPropertyPaneConfiguration() por:

    export default class ItRequestsWebPart extends BaseClientSideWebPart<IItRequestsWebPartProps> {
    // ...
      protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
        return {
          pages: [{
            header: {
              description: strings.PropertyPaneDescription
            },
            groups: [{
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('listName', {
                  label: strings.ListNameFieldLabel
                })
              ]
            }]
          }]
        };
      }
    
      protected get disableReactivePropertyChanges(): boolean {
        return true;
      }
    }
    

Para impedir que el elemento web vuelva a cargarse cuando los usuarios escriben el nombre de la lista, también ha configurado el elemento web para que use el panel de propiedades no reactivo mediante la adición del método disableReactivePropertyChanges() y el establecimiento de su valor devuelto en true.

Usar el nombre configurado de la lista desde la que se cargan los datos

Inicialmente, el nombre de la lista desde la que se deben cargar los datos se insertó en la consulta REST. Ahora que los usuarios pueden configurar este nombre, el valor configurado debe insertarse en la consulta REST antes de cargar los datos. La manera más fácil de hacerlo es moviendo el contenido del archivo script.js al archivo de elemento web principal.

  1. En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y cambie el método render() por:

    var $: any = (window as any).$;
    
    export default class ItRequestsWebPart extends BaseClientSideWebPart<IItRequestsWebPartProps> {
      public render(): void {
        this.domElement.innerHTML = `
          <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
          <table class="display ${styles.itRequests}" cellspacing="0" width="100%">
            <thead>
              <tr>
                <th>ID</th>
                <th>Business unit</th>
                <th>Category</th>
                <th>Status</th>
                <th>Due date</th>
                <th>Assigned to</th>
              </tr>
            </thead>
          </table>`;
    
        $(document).ready(() => {
          $('table', this.domElement).DataTable({
            'ajax': {
              'url': `../../_api/web/lists/getbytitle('${escape(this.properties.listName)}')/items?$select=ID,BusinessUnit,Category,Status,DueDate,AssignedTo/Title&$expand=AssignedTo/Title`,
              'headers': { 'Accept': 'application/json;odata=nometadata' },
              'dataSrc': function (data) {
                return data.value.map(function (item) {
                  return [
                    item.ID,
                    item.BusinessUnit,
                    item.Category,
                    item.Status,
                    new Date(item.DueDate),
                    item.AssignedTo.Title
                  ];
                });
              }
            },
            columnDefs: [{
              targets: 4,
              render: $.fn.dataTable.render.moment('YYYY/MM/DD')
            }]
          });
        });
      }
    
      // ...
    }
    
  2. En lugar de hacer referencia al código desde el archivo script.js, todo su contenido forma parte del método render del elemento web. En la consulta REST, ahora puede reemplazar el nombre fijo de la lista por el valor de la propiedad listName que contiene el nombre de la lista tal y como lo ha configurado el usuario. Antes de usar el valor, se aplican caracteres de escape con la función escape de lodash para impedir la inyección de script.

    En este momento, la mayor parte del código se escribe todavía con JavaScript sin formato. Para evitar problemas de compilación con la variable jQuery de $, ha tenido que definirla como tipo any antes de la definición de clase. Más adelante, cuando transforme el código a TypeScript, la reemplazará por una definición de tipo correcta.

    Como ha movido el contenido del archivo script.js al archivo de elemento web principal, script.js ya no es necesario y puede eliminarlo del proyecto.

  3. Para comprobar que el elemento web funciona del modo previsto, ejecute lo siguiente en la línea de comandos:

    gulp serve --nobrowser
    
  4. Vaya a Workbench hospedado y agregue el elemento web al lienzo. Abra el panel de propiedades del elemento web, especifique el nombre de la lista con solicitudes de TI y seleccione el botón Aplicar para confirmar los cambios.

    Ahora deben aparecer las solicitudes de TI en el elemento web.

    Solicitudes de TI cargadas de la lista configurada y mostradas en un elemento web del lado cliente de SharePoint Framework

Transformar el código JavaScript sin formato a TypeScript

El uso de TypeScript en JavaScript sin formato ofrece una serie de ventajas. No solo es más fácil mantener y refactorizar TypeScript, sino que también permite detectar errores antes. En los pasos siguientes se describe cómo transformar el código JavaScript original en TypeScript.

Agregar definiciones de tipo para las bibliotecas que se usan

Para funcionar correctamente, TypeScript requiere definiciones de tipos para las distintas bibliotecas usadas en el proyecto. Las definiciones de tipo a menudo se distribuyen como paquetes npm en el espacio de @types nombres.

  1. Ejecute lo siguiente en la línea de comandos para instalar las definiciones de tipo de jQuery y DataTables:

    npm install @types/jquery@1.10.34 @types/datatables.net@1.10.15 --save-dev --save-exact
    

    Sugerencia

    En este ejemplo, se especifica la versión exacta del paquete NPM que queremos instalar. Así, nos aseguraremos de que NPM instale un paquete de declaración de tipos que coincida con la versión de jQuery y la biblioteca DataTables que se usan en el proyecto.

    El argumento --save-dev indica a NPM que debe guardar las referencias a estos dos paquetes de la colección de devDependencies en el archivo package.json. Las declaraciones de TypeScript solo son necesarias en el desarrollo, por lo que no son deseables en la colección de dependencies.

    El argumento --save-exact indica a NPM que debe agregar referencias a la versión específica del archivo package.json y que no debe agregar la notación para habilitar las actualizaciones automáticas a una versión más reciente.

    Las definiciones de tipos de Moment.js se distribuyen junto con el paquete Moment.js. Aunque cargue Moment.js desde una dirección URL, para usar sus términos, todavía tiene que instalar el paquete de Moment.js en el proyecto.

  2. Ejecute lo siguiente en la línea de comandos para instalar el paquete de Moment.js:

    npm install moment@2.27.0 --save-exact
    

Actualizar las referencias del paquete

Para usar tipos de las definiciones de tipo instaladas, debe cambiar la forma de hacer referencia a las bibliotecas.

  1. En el editor de código, abra el archivo./src/webparts/itRequests/ItRequestsWebPart.ts y cambie la instrucción import 'jquery'; a:

    import * as $ from 'jquery';
    
  2. Al haber definido $ como jQuery, ahora puede quitar la definición local de $ que ha agregado antes:

    var $: any = (window as any).$;
    

Actualizar los archivos de elemento web principales a TypeScript

Ahora que tiene las definiciones de tipo para todas las bibliotecas instaladas en el proyecto, puede empezar a transformar el código JavaScript sin formato a TypeScript.

  1. Defina una interfaz para la información de solicitud de TI que recupere de la lista de SharePoint. En el editor de código, abra el archivo ./src/webparts/itRequests/ItRequestsWebPart.ts y, justo encima de la clase del elemento web, agregue el siguiente fragmento de código:

    interface IRequestItem {
      ID: number;
      BusinessUnit: string;
      Category: string;
      Status: string;
      DueDate: string;
      AssignedTo: { Title: string; };
    }
    
  2. Luego, en la clase de elemento web, cambie el método render() a:

    export default class ItRequestsWebPart extends BaseClientSideWebPart<IItRequestsWebPartProps> {
      public render(): void {
        this.domElement.innerHTML = `
          <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
          <table class="display ${styles.itRequests}" cellspacing="0" width="100%">
            <thead>
              <tr>
                <th>ID</th>
                <th>Business unit</th>
                <th>Category</th>
                <th>Status</th>
                <th>Due date</th>
                <th>Assigned to</th>
              </tr>
            </thead>
          </table>`;
    
          $('table', this.domElement).DataTable({
            'ajax': {
              'url': `../../_api/web/lists/getbytitle('${escape(this.properties.listName)}')/items?$select=ID,BusinessUnit,Category,Status,DueDate,AssignedTo/Title&$expand=AssignedTo/Title`,
              'headers': { 'Accept': 'application/json;odata=nometadata' },
              'dataSrc': (data: { value: IRequestItem[] }): any[][] => {
                return data.value.map((item: IRequestItem): any[] => {
                  return [
                    item.ID,
                    item.BusinessUnit,
                    item.Category,
                    item.Status,
                    new Date(item.DueDate),
                    item.AssignedTo.Title
                  ];
                });
              }
            },
            columnDefs: [{
              targets: 4,
              render: ($.fn.dataTable.render as any).moment('YYYY/MM/DD')
            }]
          });
      }
    
      // ...
    }
    
  3. Observe que la solicitud de AJAX, para recuperar los datos de la lista de SharePoint, ahora está tipada y le ayuda a asegurarse de que hace referencia a las propiedades correctas al pasarlas en una matriz a DataTables. La estructura de datos que DataTables usa para representar una fila de la tabla es una matriz de tipos combinados, por lo que, para simplificar, se ha definido como any[]. El uso del tipo any en este contexto no es incorrecto, porque los datos devueltos dentro de la propiedad dataSrc los usa DataTables internamente.

    Como va a actualizar el método render(), también ha agregado otros dos cambios. En primer lugar, ha quitado el atributo id de la tabla. Esto permite colocar varias instancias del mismo elemento web en la página. Además, ha quitado la referencia a la función $(document).ready(), que no es necesaria porque el DOM del elemento (donde se representa la tabla de datos) se establece antes del código de iniciación de DataTables.

Actualizar el complemento DataTables de Moment.js a TypeScript

La última pieza de la solución que hay que transformar a TypeScript es el complemento DataTables de Moment.js.

  1. Cambie el nombre del archivo ./src/webparts/itRequests/moment-plugin.js a ./src/webparts/itRequests/moment-plugin.ts para que lo procese el compilador de TypeScript.

  2. Abra el archivo moment-plugin.ts en el editor de código y reemplace su contenido por:

    import * as $ from 'jquery';
    import * as moment from 'moment';
    
    /* tslint:disable:no-function-expression */
    ($.fn.dataTable.render as any).moment = function (from: string, to: string, locale: string): (d: any, type: string, row: any) => string {
    /* tslint:enable */
      // Argument shifting
      if (arguments.length === 1) {
        locale = 'en';
        to = from;
        from = 'YYYY-MM-DD';
      } else if (arguments.length === 2) {
        locale = 'en';
      }
    
      return (d: any, type: string, row: any): string => {
        let m: moment.Moment = moment(d, from, locale, true);
    
        // Order and type get a number value from Moment, everything else
        // sees the rendered value
        return m.format(type === 'sort' || type === 'type' ? 'x' : to);
      };
    };
    
  3. Para empezar, cargue referencias a jQuery y Moment.js para que TypeScript sepa a qué hacen referencia las variables correspondientes. Luego, defina la función de complemento. Normalmente en TypeScript se usa la notación de flecha para las funciones (=>). Sin embargo, en este caso, como se necesita el acceso a la propiedad arguments, tiene que usar la definición de función normal. Para impedir que tslint emita una advertencia en la que se indica que no se use la notación de flecha, puede deshabilitar explícitamente la regla no-function-expression de la definición de función.

  4. Para confirmar que todo funciona del modo previsto, ejecute lo siguiente en la línea de comandos:

    gulp serve --nobrowser
    
  5. Vaya a Workbench hospedado y agregue el elemento web al lienzo. Aunque visualmente no ha cambiado nada, la nueva base de código usa TypeScript y sus definiciones de tipo para ayudarle a mantener la solución.