Usar las API de JavaScript de SharePoint para trabajar con datos de SharePoint

Este es el décimo artículo de una serie sobre los conceptos básicos de desarrollo de complementos de SharePoint hospedados en SharePoint. Primero debe familiarizarse con Complementos de SharePoint y con los anteriores artículos de esta serie, los cuales puede encontrar en Introducción a la creación de complementos de SharePoint hospedados en SharePoint | Pasos siguientes.

Nota:

Si ha estado trabajando en esta serie sobre complementos hospedados por SharePoint, hay una solución de Visual Studio que puede usar para continuar con este tema. También puede descargar el repositorio que encontrará en SharePoint_SP-hosted_Add-Ins_Tutorials y abrir el archivo BeforeJSOM.sln.

Aunque los complementos de SharePoint hospedados en SharePoint no pueden tener código en el lado del servidor, es posible tener una lógica corporativa y una interacción de tiempo de ejecución con los componentes de SharePoint en un complemento de SharePoint hospedado en SharePoint mediante JavaScript y la biblioteca de modelo de objetos de cliente de JavaScript para SharePoint. Se le llama JSOM. Tenga en cuenta la "M" al final. No lo confunda con JSON (notación de objetos JavaScript). En este artículo, usará el modelo de objetos de JavaScript para buscar y eliminar elementos antiguos de la lista Nuevos empleados en Seattle.

Crear el código de JavaScript y un botón que lo invoca

  1. Compruebe que se completó el paso siguiente del primer tutorial de esta serie:

    Abra el archivo /Pages/Default.aspx de la raíz del proyecto. Entre otras cosas, este archivo generado carga uno o ambos scripts que se hospedan en SharePoint: sp.runtime.js y sp.js. La marca para cargar estos archivos está en el control Content situado cerca de la parte superior del archivo que tiene el identificador PlaceHolderAdditionalPageHead. La revisión varía según la versión de Microsoft Office Developer Tools para Visual Studio que está usando.

    Esta serie de tutoriales requiere que ambos archivos se carguen mediante etiquetas HTML de <script>, no con etiquetas de <SharePoint:ScriptLink>. Asegúrese de que las líneas siguientes están en el control PlaceHolderAdditionalPageHead, justo encima de la línea <meta name="WebPartPageExpansion" content="full" />:

    <script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
    <script type="text/javascript" src="/_layouts/15/sp.js"></script>
    

    A continuación, busque en el archivo cualquier otra marca que también permita cargar uno de estos archivos y quite la marca redundante. Guarde y cierre el archivo.

  2. En el nodo Scripts del Explorador de soluciones, debería haber un archivo Add-in.js. Si no está, pero hay un archivo App.js, haga clic con el botón derecho en App.js y cambie el nombre por Add-in.js. Si no hay un Add-in.js o App.js, cree uno siguiendo estos pasos:

    1. Haga clic con el botón derecho en el nodo Scripts y seleccione Agregar>Nuevo elemento>Web.

    2. Seleccione Archivo JavaScript y asígnele el nombre Add-in.js.

    3. Actualice el código de la página aspx para que haga referencia al archivo JS correcto: cámbielo de:

      <script type="text/javascript" src="../Scripts/App.js"></script>
      

      a

      <script type="text/javascript" src="../Scripts/Add-in.js"></script>
      
  3. Abra Add-in.js y elimine el contenido que tenga.

  4. Agregue las siguientes líneas al archivo.

    'use strict';
    
      var clientContext = SP.ClientContext.get_current();
      var employeeList = clientContext.get_web().get_lists().getByTitle('New Employees In Seattle');
      var completedItems;
    

    Tenga en cuenta lo siguiente en relación con este código:

    • La línea 'use strict'; garantiza que el tiempo de ejecución de JavaScript en el explorador generará una excepción si sigue accidentalmente determinadas prácticas incorrectas en el JavaScript.
    • La clientContextvariable contiene unSP.ClientContext objeto que hace referencia al sitio web de SharePoint. Todo el código JSOM comienza creando u obteniendo una referencia a un objeto de este tipo.
    • La variable employeeList contiene una referencia a la instancia de lista Nuevos empleados de Seattle.
    • La variable completedItems contiene los elementos de la lista que eliminará el script: los elementos cuyo campo OrientationStage esté establecido en Completado.
  5. Para minimizar los mensajes entre el explorador del cliente y el servidor de SharePoint, JSOM usa un sistema de procesamiento por lotes. Solo una función, SP.ClientContext.executeQueryAsync, envía realmente mensajes al servidor (y recibe respuestas).

    Las llamadas a la API de JSOM que se incluyen entre las llamadas de executeQueryAsync se agrupan y se envían al servidor en un lote la próxima vez que se llama a executeQueryAsync. Pero no es posible llamar a un método de un objeto JSOM a menos que el objeto se haya reducido para el cliente en una llamada anterior de executeQueryAsync.

    El script va a llamar al método SP.ListItem.deleteObject de cada elemento completado en la lista, con dos llamadas de executeQueryAsync: una para obtener una colección de los elementos completos de la lista, y una segunda para agrupar las llamadas de deleteObject y enviarlas al servidor para la ejecución.

    Empiece por crear un método para obtener los elementos de lista desde el servidor. Agregue el siguiente código al archivo.

    function purgeCompletedItems() {
    
      var camlQuery = new SP.CamlQuery();
      camlQuery.set_viewXml(
        '<View><Query><Where><Eq>' +
          '<FieldRef Name=\'OrientationStage\'/><Value Type=\'Choice\'>Completed</Value>' +
        '</Eq></Where></Query></View>');
      completedItems = employeeList.getItems(camlQuery);
    }
    
  6. Cuando esas líneas se envían al servidor y se ejecutan en él, crean una colección de elementos de lista, pero el script debe reducir esa colección para el cliente. Esto se realiza con una llamada a la función SP.ClientContext.load, así que agregue la siguiente línea al final del método.

    clientContext.load(completedItems);
    
  7. Agregue una llamada de executeQueryAsync. Este método tiene dos parámetros que son funciones de devolución de llamada. La primera se ejecuta si el servidor ejecuta correctamente todos los comandos del lote. Si se produce un error en el servidor por algún motivo, se ejecuta la segunda. Creará estas dos funciones en los pasos siguientes. Agregue la línea siguiente al final del método.

    clientContext.executeQueryAsync(deleteCompletedItems, onGetCompletedItemsFail);
    
  8. Finalmente, agregue la línea siguiente al final del método.

    return false;
    

    Si se devuelve false al botón ASP.NET que llamará a la función, se cancela el comportamiento predeterminado de los botones ASP.NET, que es volver a cargar la página. Volver a cargar la página provocaría una recarga del archivo Add-in.js. Y eso, a su vez, reiniciaría el objeto clientContext.

    Si esta recarga se completa entre el momento en que executeQueryAsync envía la solicitud y el momento en que el servidor de SharePoint devuelve la respuesta, el objeto original clientContext no existirá para procesar la respuesta. La función se detendrá sin éxito ni fracaso de las devoluciones de llamada ejecutadas. (El comportamiento exacto podría variar según el explorador).

  9. Agregue la siguiente función, deleteCompletedItems, al archivo. Esta es la función que se ejecuta si la función purgeCompletedItems es correcta. Tenga en cuenta lo siguiente en relación con este código:

    • El método SP.ListItem.get_id devuelve el identificador del elemento de lista. Cada elemento de la matriz es un objeto SP.ListItem.
    • El método SP.List.getItemById devuelve el objeto SP.ListItem con el identificador especificado.
    • El método SP.ListItem.deleteObject marca el elemento de lista que se eliminará en el servidor cuando se realice la llamada de executeQueryAsync. Antes de que se puedan eliminar, los elementos de la lista deben copiarse de la colección que se envía desde el servidor a una matriz. Si el script ha llamado al método deleteObject para cada elemento directamente en el bucle while, JavaScript podría producir un error al quejarse de que la longitud de la colección se está cambiando mientras la enumeración está en curso.

    El mensaje de error no es verdadero de forma literal, porque el elemento no elimina realmente de ninguna parte hasta que las llamadas deleteObject se agrupen y se envíen al servidor, pero el JSOM está diseñado para imitar las excepciones que deberían producirse en el servidor (donde el código no debe cambiar el tamaño de una colección mientras se está enumerando la colección). Sin embargo, las matrices tienen un tamaño fijo, por lo que las llamadas deleteObject en un elemento de una matriz eliminan el elemento de la lista, pero no cambian el tamaño de la matriz.

    function deleteCompletedItems() {
    
      var itemArray = new Array();
      var listItemEnumerator = completedItems.getEnumerator();
    
      while (listItemEnumerator.moveNext()) {
        var item = listItemEnumerator.get_current();
        itemArray.push(item);
      }
    
      var i;
      for (i = 0; i < itemArray.length; i++) {
        itemArray[i].deleteObject();
      }
    
      clientContext.executeQueryAsync(onDeleteCompletedItemsSuccess, onDeleteCompletedItemsFail);
    }
    
  10. Agregue la siguiente función, onDeleteCompletedItemsSuccess, al archivo. Esta es la función que se ejecuta si se eliminan correctamente los elementos completados (o si no hay ningún elemento completado en la lista).

    La línea location.reload(true); hace que la página se vuelva a cargar desde el servidor. Es muy útil porque el elemento web de la vista de lista en la página aún muestra los elementos completados hasta que se actualice la página. El archivo Add-in.js también se vuelve a cargar, pero esto no causa un problema porque no lo hará de una forma que interrumpa una función JavaScript en curso.

    function onDeleteCompletedItemsSuccess() {
      alert('Completed orientations have been deleted.');
      location.reload(true);
    }
    
  11. Agregue al archivo las dos funciones siguientes de devolución de llamada en caso de error.

    // Failure callbacks
    
    function onGetCompletedItemsFail(sender, args) {
      alert('Unable to get completed items. Error:' + args.get_message() + '\n' + args.get_stackTrace());
    }
    
    function onDeleteCompletedItemsFail(sender, args) {
      alert('Unable to delete completed items. Error:' + args.get_message() + '\n' + args.get_stackTrace());
    }
    
  12. Abra el archivo default.aspx y busque el elemento asp:Content con el identificador PlaceHolderMain.

  13. Agregue la siguiente marcación entre el elemento WebPartPages:WebPartZone y el primero de los dos elementos asp:Hyperlink. El valor del controlador OnClientClick es return purgeCompletedItems() en lugar de solo purgeCompletedItems(). El false que devuelve la función indica a ASP.NET que no vuelva a cargar la página.

    <p><asp:Button runat="server" OnClientClick="return purgeCompletedItems()" ID="purgecompleteditemsbutton" Text="Purge Completed Items" /></p>
    
  14. Vuelva a compilar el proyecto en Visual Studio.

  15. Para minimizar la necesidad de establecer manualmente la Fase de orientación de elementos de lista en Completada mientras se prueba el complemento, abra el archivo elements.xml de la instancia de lista NewEmployeesInSeattle (no elements.xml de la plantilla de lista NewEmployeeOrientation) y agregue la marcación <Field Name="OrientationStage">Completed</Field> como último elemento secundario a uno o más de los elementos Row.

    El siguiente es un ejemplo del aspecto del elemento Rows.

    <Rows>
      <Row>
        <Field Name="Title">Tom Higginbotham</Field>
        <Field Name="Division">Manufacturing</Field>
        <Field Name="OrientationStage">Completed</Field>
      </Row>
      <Row>
        <Field Name="Title">Satomi Hayakawa</Field>
        <Field Name="OrientationStage">Completed</Field>
      </Row>
      <Row>
        <Field Name="Title">Cassi Hicks</Field>
      </Row>
      <Row>
        <Field Name="Title">Lertchai Treetawatchaiwong</Field>
      </Row>
    </Rows>
    

Ejecutar y probar el complemento

  1. Habilite las ventanas emergentes en el explorador que Visual Studio usa durante la depuraci?n.

  2. Use la tecla F5 para implementar y ejecutar el complemento. Visual Studio instala temporalmente el complemento en el sitio de SharePoint de prueba y ejecuta el complemento inmediatamente.

  3. Se abre la página principal del complemento con uno o más elementos en la lista con Fase de orientación en Completada.

    Figura 1. Lista antes de la purga de los elementos completados

    La lista

  4. Cuando la página de inicio del complemento se haya cargado, seleccione el botón Purgar elementos completados. Si la operación se realiza correctamente (es decir, si no hay mensajes de error), todos los elementos Completados se eliminan y se verá una ventana emergente que indica Las orientaciones completadas se eliminaron.

  5. Cierre la ventana emergente. La página se vuelve a cargar y los elementos Completados ya no están en el elemento web de vista de lista.

    Figura 2. Lista después de la purga de los elementos completados

    La lista

  6. Para finalizar la sesión de depuración, cierre la ventana del explorador o detenga la depuración en Visual Studio. Cada vez que seleccione F5, Visual Studio retirará la versión anterior del complemento e instalará la más reciente.

  7. Trabajará con este complemento y con la solución de Visual Studio en otros artículos. Es recomendable que vuelva a retirar el complemento cuando deje de trabajar con él por un tiempo. Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Retirar.

Pasos siguientes

En el siguiente artículo de esta serie, agregaremos JavaScript a una página en la web de complemento que funciona con los datos de SharePoint en la web de host: Trabajar con datos de web de host de JavaScript en la web de complemento.