Mostrando entradas con la etiqueta JSLink. Mostrar todas las entradas
Mostrando entradas con la etiqueta JSLink. Mostrar todas las entradas

domingo, 21 de septiembre de 2014

Cómo utilizar el debugger de Visual Studio con client side rendering

Primero verifico que esté desmarcado las siguientes opciones en las propiedades avanzadas del IE.

image

(function () {
    var itemCtx = {};
    itemCtx.Templates = {};
   
    itemCtx.Templates.Header = "<table>";
    itemCtx.Templates.Footer = "</table>";
    itemCtx.Templates.Fields = { 'Title': { 'View': ItemOverrideFun}};
    itemCtx.BaseViewID = 1;
    itemCtx.ListTemplateType = 101;         
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
})();

function ItemOverrideFun(ctx) {   
   debugger;
    var title = ctx.CurrentItem.Title;
    var fileRef = ctx.CurrentItem["FileRef"];
    var fileLeafRef = ctx.CurrentItem["FileLeafRef"];  
       var htmlToDeploy = "<a style='color:#000; font-weight:bold' href='" + ctx.CurrentItem["FileRef"] + "'>" + ctx.CurrentItem.Title + "</a><br><span>" + formattedDate(ctx.CurrentItem.Modified)  + " for <b><font color='#f58228'> "+ ctx.CurrentItem.Customer[0].lookupValue +"</font></b></span>";
 
    return htmlToDeploy;
}

En la función ItemOverrideFun, vemos la palabra debugger, esta es una palabra reservada que permite invocar el JIT (just in time) debugger

Al ejecutarse esta línea en el IE, me lanza la siguiente ventana

image

Al abrir el Visual Studio 2013, veo el stack de llamadas y me permite debuggear con VS

image

Si marca la variable htmlToDeploy, y selecciono Add Watch

image

image

Puedo ver el html que se renderiza en la página de forma fácil

image

Si veo en la página como queda,

image

domingo, 14 de septiembre de 2014

Cómo definir correctamente nuestros archivos de CSR (Client Side Rendering) o jslink

Un problema que suele pasar con jslink es cuando tenemos una página con dos o más webparts que cada uno tiene asignado un archivo jslink. Puede pasar que creamos nuestras funciones de override de campos/header/footer/grouping/etc con nombres iguales en cada archivo jslink.

Ej:

En el web part 1 llama al archivo documentosCSR.js

En el web part 2 llama al archivo taskCSR.js

Ambos archivos tienen un override de la view del campo “Title” y ambos archivos usan la función titleFieldOverride(ctx).

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function titleFieldOverride(ctx)
{

}

Que pasa en estos casos? El último archivo js que se cargue será el que prevalece, lo cual puede ocasionar errores dificiles de detectar.

Para ello, siempre crea los archivos jslink con funciones definidas en global namespaces de javascript. Los namespaces nos permiten definir variables, funciones dentro de un “contenedor” ( a efectos prácticos es un objeto ), la idea de trasfondo consiste en que cada archivo jslink utilice su propio namespace para que de esta forma no perdamos funcionalidad al “solapar” el código.

Veamos un ejemplo correcto.

En el archivo documentosCSR.js defino el código de la siguiente manera

var solutionDocumentosCSR = solutionDocumentosCSR || {};
solutionDocumentosCSR.Fields = (function () {
    
    function convertirFecha(fecha) {
        /* convierto la fecha al formato ddMMYYY */
    };
 
    return {
        titleFieldOverride: function (ctx) {
            var html = "<div><strong>" + ctx.CurrentItem.Title + "</strong></div>";
           //aca puedo usar la funcion convertirFecha la cual esta definida dentro del mismo namespace
            return html;
        }
    }
})();

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': solutionDocumentosCSR.Fields.titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

En el otro archivo  taskCSR.js defino el código de la siguiente manera

var solutionTasksCSR = solutionTasksCSR || {};
solutionTasksCSR.Fields = (function () {
    
    function convertirFecha(fecha) {
        /* convierto la fecha al formato mmDDyyyy */
    };
 
    return {
        titleFieldOverride: function (ctx) {
            var html = "<div><strong>" + ctx.CurrentItem.Title + "</strong></div>";
            //aca puedo usar la funcion convertirFecha la cual esta definida dentro del mismo namespace, y no se toma en cuenta la función definida en el otro namespace
            return html;
        }
    }
})();

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': solutionTasksCSR.Fields.titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

sábado, 13 de septiembre de 2014

Paginado mediante jslink en Sharepoint 2013 (Paging jslink)

En este ejemplo lo que voy a mostrar es cómo realizar un paginado mediante jslink.

Current enviroment:

  • Enabled Minimal Download Strategy
  • Sharepoint 2013 - 15.0.4551.1511

Tengo la siguiente lista de items y lo que voy a hacer es paginar cada 5 items

image

Creo una página, agrego el web part de la lista y limito la cantidad de items que puedo mostrar.

image

Lo que genera la siguiente vista.

image

Pero que pasa si agregamos código jslink al web part? Por ejemplo el siguiente jslink (no genera override de ninguna funcionalidad)

(function () {

    var itemCtx = {};
    itemCtx.Templates = {};
    itemCtx.BaseViewID = 1;
    itemCtx.ListTemplateType = 100;   
   
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);

})();

lo subo a http://urldelsite/_catalogs/masterpage/ con el contenttype Javascript Display Template

image

En el web part que había agregado anteriormente, le seteo el archivo jslink.

~sitecollection/_catalogs/masterpage/csrpagging.js

Presten atención al tilde (~)

image`

Vemos que sigue funcionando el pagging.

image

Que pasa si agregamos el siguiente código.

(function () {

    var itemCtx = {};
    itemCtx.Templates = {};

    itemCtx.Templates.Header = "<table>";
   
    itemCtx.BaseViewID = 1;
    itemCtx.ListTemplateType = 100;   
   itemCtx.Templates.Footer = "</table>"

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);

})();

Como se ve en la siguiente imagen, ya no aparece el header ni el footer del web part.

image

Entonces cómo hacemos para agregar el paginado mediante jslink y darle más funcionalidad al footer.


(function () {

    var itemCtx = {};
    itemCtx.Templates = {};

    itemCtx.Templates.Header = "<table>";
   
    itemCtx.BaseViewID = 1;
    itemCtx.ListTemplateType = 100;   
    itemCtx.Templates.Footer = pagingControl;

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);

})();

function pagingControl(ctx)
{       
        var footerHtml = '<table class="ms-bottompaging"><tr><td>';
        var next = ctx.ListData.NextHref;  
        var prev = ctx.ListData.PrevHref;
  
        if ((next != undefined) && (prev != undefined ))
        {
            footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + prev + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-left' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>";
            footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + next + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-right' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>";
            footerHtml += "</td></tr></table>";           
            footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
            return footerHtml;       
        }
        else
        {
            if (next != undefined)
            {
                footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + next + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-right' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>";
                footerHtml += "</td></tr></table>";
                footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
                return footerHtml;       

            }
            else
            {
                if (prev != undefined)
                {
                    footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + prev + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-left' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>";
                    footerHtml += "</td></tr></table>";
                    footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
                    return footerHtml;       
                }
                else
                    return "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
            }       
        }
       
}

image image

image

image

En el caso que quisieramos agregar la información de la cantidad de items, podriamos reemplazar la función pagingControl por la siguiente.


function pagingControl(ctx)
{      
       var firstRow = ctx.ListData.FirstRow;
        var lastRow  = ctx.ListData.LastRow;
        var footerHtml = '<table class="ms-bottompaging"><tr><td>';
        var next = ctx.ListData.NextHref;  
        var prev = ctx.ListData.PrevHref;
  
        if ((next != undefined) && (prev != undefined ))
        {
            footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + prev + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-left' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>";
            footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + next + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-right' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>&nbsp" + firstRow  + " de " +  lastRow;
            footerHtml += "</td></tr></table>";           
            footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
            return footerHtml;       
        }
        else
        {
            if (next != undefined)
            {
                footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + next + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-right' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>&nbsp" + firstRow  + " de " +  lastRow;
                footerHtml += "</td></tr></table>";
                footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
                return footerHtml;       

            }
            else
            {
                if (prev != undefined)
                {
                    footerHtml += "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='javascript:void(0);' onclick=\"RefreshPageTo(event, &quot;" + prev + "&quot;);return false;\"><span class='ms-promlink-button-image'><img class='ms-promlink-button-left' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>&nbsp" + firstRow  + " de " +  lastRow;
                    footerHtml += "</td></tr></table>";
                    footerHtml += "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
                    return footerHtml;       
                }
                else
                    return "<HR style='margin-left:-20px' COLOR='green' WIDTH='106%'>";
            }       
        }
       
}

Lo cual permite mostrar la cantidad de items que se ve en la vista (Ej: 6 de 10)

image

Cómo pueden ver en el código se hace uso de una función llamada RefreshPageTo, que está definida en el archivo INPLVIEW.js,

Ingreso al archivo debug, así es más fácil para ver la función

/_layouts/15/inplview.debug.js

image

Les dejo el código js en el siguiente link: http://1drv.ms/1wjDBN5

Podrán encontrar más post sobre jslink en el siguiente tag: http://todosharepoint.blogspot.com.ar/search/label/JSLink

domingo, 29 de junio de 2014

JSlink para una lista de Anuncios

Voy a mostrar un step by step para mejorar la interfaz de una lista de anuncios mediante jslink. Ej de cómo quedaría.

image

Agrego un App de Anuncios

image

image

image

Agrego una página para mi homepage

image

image

Agregamos el web part de anuncios

image

image

Una vez agregado el web part, actualizamos la vista default de la app. Agregamos los siguientes campos:

image

Agregamos un par de ejemplos de anuncios

image

Ahora lo importante, creen un archivo de javascript (Ej: CSRNews.js) y agreguen lo siguiente

(function () {

var itemCtx = {};
itemCtx.Templates = {};

itemCtx.Templates.Header = "<table>";
itemCtx.Templates.Item = ItemOverrideFun;
itemCtx.Templates.Footer = "</table>";

itemCtx.BaseViewID = 1;
itemCtx.ListTemplateType = 104;

SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);

})();

function ItemOverrideFun(ctx) {

var _announcementTitle = ctx.CurrentItem.Title;
var _announcementDesc = ctx.CurrentItem.Body;
var _announcementID = ctx.CurrentItem.ID;
var fecha = ctx.CurrentItem.Modified;

var monthNames = [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio","Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ];
var d = new Date(fecha);
 
return "<tr><td style='vertical-align:top'>" + "<div class='dateBox'><div class='dayDateBox'>" + d.getDay() + "</div><div class='monthDateBox' >" +  monthNames[d.getMonth()] + "</div></div>"+ "</td><td><b>" + _announcementTitle + "</b>" + _announcementDesc +"<a href='/Lists/Announcements/DispForm.aspx?ID='"+ _announcementID + "'> Read More…</a><p></p></td></tr>";
}

Suba el archivo js, a la siguiente librería

image

image

Editamos el web part y agregamos lo siguiente en la sección de “Varios\Vinculo js”

image

~site/SiteAssets/CSRNews.js

image

Ahora cambiamos el atributo vista selecciona a “Todos los Elementos”

image

La vista nos queda de la siguiente manera

image

A continuación agrego un web part Script editor

image

y agrego el siguiente estilo de css

<style>
/*  date Box */
.dateBox
{
    width: 50px;
    height: 50px;
    background-color: #f58228;
    padding-left: 8px;
    margin-right: 5px;
    margin-top:0px;
}
.dayDateBox
{
    font-size: 25px;
    line-height: 25px;
    color: white;
    padding-top: 3px;
}
.monthDateBox
{
    font-size: 12px;
    color: white;
}
</style>

image

Guarda la página, y el web part de anuncios quedo de la siguiente manera.

image