Arquitectura, buenas prácticas y desarrollo sobre la nueva herramienta de Microsoft SharePoint 2016

[SharePoint APP] Introducción al modelo de objetos cliente de JavaScript

LogoJ queryEn la anterior post vimos como podíamos hacer uso las operaciones básicas de la API Rest, en este post vamos a introducir un poco el modelo de objetos en cliente utilizando JavaScript. Por lo general JavaScript ha sido un lenguaje poco querido por los desarrolladores de .NET, en esta nueva versión de SharePoint nos obligan un poco a reciclarnos y aprender  este lenguaje de programación y sacar todas sus bondades (que las tiene). No va a ser en este post en el que las describa,debido a que aún no dispongo de los conocimientos propios para poder explicar este lenguaje y aconsejar sobre él, esta tarea mejor para expertos en esta materia como mi compañero Iwan (Return Value). Pero si que os voy a introducir operaciones que se pueden utilizar haciendo uso de este lenguaje contra nuestro querido Servidor.

Para empezar con este ejemplo abrimos el Visual Studio 2012, seleccionamos un proyecto Office/SharePoint y escogemos la plantilla Aplicación para SharePoint 2013, y indicamos el nombre de nuestro sitio y seleccionamos el tipo de Alojamiento (AutoHosted ya que va a estar alojado en nuestro Office 365) tal y como se muestra en la siguiente imagen:

Proyecto AutoHostedUna vez nos crea el proyecto vemos que nos ha creado una Página aspx y una carpeta con Script, en esta carpeta con Script añadimos un fichero javascript llamado App.js (En el que posteriormente añadiremos la lógica que le queremos implementar en la aplicación). Pero antes de nada el primer paso es hacer referencia a las librerías que vamos a utilizar para ello tendremos que añadir las dentro de la página donde las vayamos a utilizar en nuestro caso en el Default.aspx:

<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js">// <![CDATA[

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

// ]]></script>
<script type="text/javascript" src="/_layouts/15/sp.js">// <![CDATA[

// ]]></script>

La primera de ellas hace referencia referencia a la biblioteca AJAX desde la CDN de Microsoft y las otras dos son las librerías propias para obtener las conexiones básicas de SharePoint.
El primer ejemplo de hoy vamos a ver las listas que tenemos en nuestro sitio para ello nos basta con un código como el siguiente:


function retrieveAllListProperties(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    this.collList = oWebsite.get_lists();
    clientContext.load(collList);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var listInfo = '';
    var listEnumerator = collList.getEnumerator();
    while (listEnumerator.moveNext()) {
        var oList = listEnumerator.get_current();
        listInfo += 'Title: ' + oList.get_title() + ' Created: ' +
            oList.get_created().toString() + '\n';
    }
    alert(listInfo);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

Para las personas que hemos trabajado un poco con el modelo de objetos de cliente de .NET la verdad es que es prácticamente igual, tenemos los mismos métodos y la única dificultad es conocer JavaScript.
Otra de las opciones que podemos hacer utilizando, es hacer consultas CAML sobre los elementos de una lista para ello con un ejemplo como el siguiente lo solucionamos de una manera muy sencilla:

function retrieveListItems(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(
        '' +
        '1' +
        '10'
    );
    this.collListItem = oList.getItems(camlQuery);
    clientContext.load(collListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded(sender, args) {
    var listItemInfo = '';
    var listItemEnumerator = collListItem.getEnumerator();
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        listItemInfo += '\nID: ' + oListItem.get_id() +
            '\nTitle: ' + oListItem.get_item('Title') +
            '\nBody: ' + oListItem.get_item('Body');
    }
    alert(listItemInfo.toString());
}
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

Ahora como podemos hacer operaciones de añadir, modificar, elementos sobre una lista:
Para crear elementos de una lista debe crear un objeto ListItemCreationInformation, establecer sus propiedades y pasarlo como parámetro a la función addItem(parameters) del objeto List. Establezca las propiedades en el objeto de elemento de lista que este método devuelve y luego llame a la función update(), como se ve en el ejemplo siguiente:

function createListItem(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');

    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = oList.addItem(itemCreateInfo);
    oListItem.set_item('Title', 'My New Item!');
    oListItem.set_item('Body', 'Hello World!');
    oListItem.update();
    clientContext.load(oListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );
}
function onQuerySucceeded() {
    alert('Item created: ' + oListItem.get_id());
}
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

Para actualizar un elemento de lista Para establecer la mayoría de las propiedades del elemento de lista, se puede usar un indizador de columna para realizar una asignación y llamar a la función update() para que los cambios se realicen al llamar a executeQueryAsync(succeededCallback, failedCallback). En el ejemplo siguiente se establece el título del tercer elemento de la lista de anuncios.

Function updateListItem(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
    this.oListItem = oList.getItemById(3);
    oListItem.set_item('Title', 'My Updated Title');
    oListItem.update();
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );
}
function onQuerySucceeded() {
    alert('Item updated!');
}
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

Para eliminar un elemento de lista: llame a la función deleteObject() del objeto. En el siguiente ejemplo se usa la función getItemById(id) para devolver el segundo elemento de la lista y luego se elimina el elemento. SharePoint mantiene los identificadores de enteros de los elementos dentro de las colecciones aunque se hayan eliminado. Por ejemplo, el segundo elemento de una lista podría no tener el 2 como identificador. Si se llama a la función deleteObject() para un elemento que no existe, se devuelve la excepción ServerException.

function deleteListItem(siteUrl) {
    this.itemId = 2;
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
    this.oListItem = oList.getItemById(itemId);
    oListItem.deleteObject();
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );
}
function onQuerySucceeded() {
    alert('Item deleted: ' + itemId);
}
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

Autentificación
Para realizar la autentificación al hacer llamadas entre distintos dominios ya que si queremos realizar llamadas al sitio donde este alojado SharePoint necesitaremos de alguna forma autentificarnos, al alojar la APP dentro de un SharePoint Online todo es más sencillo pero hace falta realizar algunas modificaciones en las llamadas y esas no es otra que llamar a esta función SP.ProxyWebRequestExecutorFactory (que hace que sea transparente la invocación desde una APP al contenido que tenemos dentro de nuestro site. Por ejemplo si queremos consultar el titulo de nuestro Site nos hace falta el siguiente código:

function execCrossDomainRequest() {
    // context: The ClientContext object provides access to
    //      the web and lists objects.
    // factory: Initialize the factory object with the
    //      app web URL.
    var context;
    var factory;
    var appContextSite;

    context = new SP.ClientContext(appweburl);
    factory = new SP.ProxyWebRequestExecutorFactory(appweburl);
    context.set_webRequestExecutorFactory(factory);
    appContextSite = new SP.AppContextSite(context, hostweburl);

    this.web = appContextSite.get_web();
    context.load(this.web);

    //Execute the query with all the previous
    //  options and parameters
    context.executeQueryAsync(
        Function.createDelegate(this, successHandler),
        Function.createDelegate(this, errorHandler)
    );
    // Function to handle the success event.
    // Prints the host web's title to the page.
    function successHandler() {
        document.getElementById("HostwebTitle").innerHTML =
            "<b>" + this.web.get_title() + "</b>";
    }

    // Function to handle the error event.
    // Prints the error message to the page.
    function errorHandler(data, errorCode, errorMessage) {
        document.getElementById("HostwebTitle").innerText =
            "Could not complete cross-domain call: " + errorMessage;
    }
}

Conclusión

Con estos ejemplos son solo unas de las acciones básicas que podemos hacer con el modelo de objetos cliente de JavaScript, como hemos visto sino lo ponemos en contexto no sabemos bien si es JavaScript o bien es C#.
Ha diferencia de lo que ocurría en la versión de 2010, ahora con el modelo de objetos en cliente podemos hacer lo mismo que con el modelo de objetos de servidor, lo cual es una grandisima ventaja ya que dado que ahora los requisitos son de multidispositivo bien sea tablets, smartphone, o los antiguos navegadores podemos realizar aplicaciones que utilicen SharePoint en alguna de sus variantes y podemos hacer aplicaciones de calidad. Ahora que disponemos de las herramientas oportunas no nos queda otra que potenciar nuestra comprensión sobre JavaScript e introducir sus mejoras en nuestros desarrollos.

mm

Sobre Adrián Díaz

Adrián Díaz es Ingeniero Informático por la Universidad Politécnica de Valencia. Es MVP de Microsoft en la categoría Office Development desde 2014, MCPD de SharePoint 2010, Microsoft Active Profesional y Microsoft Comunity Contribuitor 2012. Cofundador del grupo de usuarios de SharePoint de Levante LevaPoint. Lleva desarrollando con tecnologías Microsoft más de 10 años y desde hace 3 años está centrado en el desarrollo sobre SharePoint. Actualmente es Software & Cloud Architect Lead en ENCAMINA.
Esta entrada ha sido publicada en APP. Enlace permanente.
Suscríbete a Desarrollando sobre SharePoint

Suscríbete a Desarrollando sobre SharePoint

Recibe todas las actualizaciones semanalmente de nuestro blog

You have Successfully Subscribed!

ENCAMINA, piensa en colores