Paginacion en Sharepoint Hosted Add-In con JSOM

En este post vamos a ver un ejemplo de como hacer un SharePoint hosted Add-In el cual despliega una lista en el Add-In Web y luego una pagina de consulta de esta lista pero con paginacion incluida.

Como pueden ver la estrucutra del Proyecto, tiene un webpart llamado Sorting.aspx el cual es la pagina encargada de hacer la consulta y llenado (vista), y Sorting.js que es la parte functional de javascript.

<%@ Page language="C#" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<WebPartPages:AllowFraming ID="AllowFraming" runat="server" />

<html>  
<head>  
    <title></title>
    <script type="text/javascript" src="../Scripts/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" src="../_layouts/MicrosoftAjax.js"> </script>
    <script type="text/javascript" src="/_layouts/15/sp.runtime.debug.js"></script>
    <script type="text/javascript" src="/_layouts/15/sp.debug.js"></script>

    <!-- Add your JavaScript to the following file -->
    <script type="text/javascript" src="../Scripts/Sorting.js"></script>
</head>  
<body>  
    <div class="main">
        <div id="content">
        </div>
        <div class="pager">
            <button id="btnBack" type="button">< Back</button>
            <span id="pageInfo"></span>
            <button id="btnNext" type="button">Next ></button>
        </div>
    </div>
</body>  
</html>  

En el html solo incluimos las librerias requeridas de SharePoint, y Sorting.js que es la encargada de toda la ordenacion.

var context,  
    web,
    spItems,
    position,
    nextPagingInfo,
    previousPagingInfo,
    listName = 'ContactsList',  // Nombre de la lista
    pageIndex = 1, // Pagina inicial
    pageSize = 4, // Tamano de la pagina
    list,
    camlQuery,
    sortColumn = 'FirstName'; // Columna de ordenacion

// Al cargar el DOM ejecutamos la logica de llenar la lista y configurar la paginacion.
$(document).ready(function () {
    context = SP.ClientContext.get_current();
    list = context.get_web().get_lists().getByTitle(listName);
    camlQuery = new SP.CamlQuery();

    $("#btnNext").click(function () {  //Ar darle click al boton de pagina siguiente
        pageIndex = pageIndex + 1;
        if (nextPagingInfo) {
            position = new SP.ListItemCollectionPosition();
            position.set_pagingInfo(nextPagingInfo);
        }
        else {
            position = null;
        }

        GetListItems();
    });

    $("#btnBack").click(function () { //Al darle click al boton de pagina atras.
        pageIndex = pageIndex - 1;
        position = new SP.ListItemCollectionPosition();
        position.set_pagingInfo(previousPagingInfo);
        GetListItems();
    });

    GetListItems();
});

//Obtenemos los elementos de la lista.
function GetListItems() {  
    camlQuery.set_listItemCollectionPosition(position);
    camlQuery.set_viewXml("<View>" +
                                "<ViewFields>" +
                                       "<FieldRef Name='FirstName'/>" +
                                       "<FieldRef Name='Title'/>" +
                                       "<FieldRef Name='Company'/>" +
                                  "</ViewFields>" +
                               "<Query>" +
                                    "<OrderBy>" +
                                      "<FieldRef Name='" + sortColumn + "' Ascending='true' />" +
                                    "</OrderBy>" +
                               "</Query>" +
                               "<RowLimit>" + pageSize + "</RowLimit></View>");
    spItems = list.getItems(camlQuery);
    context.load(spItems);
    context.executeQueryAsync(
            Function.createDelegate(this, onSuccess),
            Function.createDelegate(this, onFail)
        );
}


// Todo bien.
function onSuccess() {  
    var listEnumerator = spItems.getEnumerator();
    var items = [];
    var item;
    while (listEnumerator.moveNext()) {
        item = listEnumerator.get_current();
        items.push("<td>" + item.get_item('FirstName') + "</td><td>" + item.get_item('Title') + "</td><td>" + item.get_item('Company') + "</td>");
    }
    var content = "<table><tr><th>First Name</th><th>Last Name</th><th>Company</th></tr><tr>"
                + items.join("</tr><tr>") + "</tr></table>";
    $('#content').html(content);
    managePagerControl();
}

//Configuracion de los controles
function managePagerControl() {  
    if (spItems.get_listItemCollectionPosition()) {
        nextPagingInfo = spItems.get_listItemCollectionPosition().get_pagingInfo();
    } else {
        nextPagingInfo = null;
    }
    $("#pageInfo").html((((pageIndex - 1) * pageSize) + 1) + " - " + ((pageIndex * pageSize) - (pageSize - spItems.get_count())));
    previousPagingInfo = "PagedPrev=TRUE&Paged=TRUE&p_ID=" + spItems.itemAt(0).get_item('ID') + "&p_" + sortColumn + "=" + encodeURIComponent(spItems.itemAt(0).get_item(sortColumn));
    if (pageIndex <= 1) {
        $("#btnBack").attr('disabled', 'disabled');
    }
    else {
        $("#btnBack").removeAttr('disabled');
    }

    if (nextPagingInfo) {
        $("#btnNext").removeAttr('disabled');
    }
    else {
        $("#btnNext").attr('disabled', 'disabled');
    }
}

// Todo mal
function onFail(sender, args) {  
    alert('Failed to get items. Error:' + args.get_message());
}

Eso es todo, el ejemplo complete lo encuentran en:
github