Tu primera app con Sencha Touch

Ejecutando funciones dentro de un template Más videos

Descripción del tema

En el tema anterior vimos como desplegar los fields de un record en un dataview de manera dinámica, en este tutorial vamos a ver como modificar el contenido de cada field a desplegar, esto por que en algunas ocasiones vamos a necesitar desplegar otra cosa diferente a solo texto, tal es el caso del campo art, donde desplegaremos una imagen.

Para desplegar contenido adicional dentro de cada celda lo haremos de dos manera, primero permitiremos definir un template en las columnas, esto nos permitirá poder definir el html que necesitemos desplegar en cada celda. En segundo lugar vamos a dar la posibilidad de realizar cierta lógica antes de renderizar la celda, para eso crearemos una función llamada renderer que ejecutaremos antes imprimir el contenido final de la celda.

Vamos a modificar las columnas en la clase Results (app/view/Results.js) de la siguiente manera:

Ext.define('Itunes.view.Results', {
    extend  : 'Bleext.view.grid.Grid',
    xtype   : 'results',
    requires: [
        
    ],

    config: {
        columns : [
            //Step 1
            {text:'Art',dataIndex:'artwork',tpl:'<img src="{artwork}" />'},
            {text:'Name',dataIndex:'name'},
            {text:'Artist',dataIndex:'artist'},
            {text:'Duration',dataIndex:'duration'},
            {text:'Albumn',dataIndex:'albumn'},
            {text:'Genre',dataIndex:'genre'},
            //Step 2
            {text:'Price',dataIndex:'price',renderer:function(value){return value + value * 0.1}}
        ],
        store   : {
            //...
        }
    }
});
  1. En el primer paso estamos agregando una nueva propiedad tpl, aquí vamos a definir un template que aplicaremos a las celdas de esa columna únicamente, en este caso estamos definiendo una imagen pero las posibilidades son infinitas, con esto daremos a nuestro grid mucha flexibilidad.
  2. En el paso dos estamos definiendo una función llamada renderer, esta función estará ejecutándose por cada celda en esa columna y lo que regrese será lo que imprimiremos en esa celda, en este ejemplo le estamos aumentando el 10% al precio.

Si ejecutamos nuestro código en este momento, no veremos ningún cambio, esto es porque no hemos creado la funcionalidad en nuestro grid, debemos detectar cuando se defina un template en la columna y aplicarlo a la celda, el renderer tampoco funciona.

Vamos a modificar el código de la clase Grid (package/Bleext/src/view/grid/Grid.js) de la siguiente manera.

Ext.define('Bleext.view.grid.Grid', {
    extend: 'Ext.Container',
    
    //...

    buildDataview   : function(){
        var me      = this,
            store   = me.getStore(),  //Step 1
            columns = me.getColumns(),
            column,
            html = [],
            tpl,
            len,
            i;

        for(i=0,len=columns.length;i<len;i++){
            column = columns[i];

            if(column.width){
                //Step 2
                html.push('<div class="bleext-grid-cell" style="width:'+column.width+'px;">{[this.getRenderer('+i+',xindex)]}</div>');
            }else{
                //Step 2
                html.push('<div class="bleext-grid-cell" style="flex:'+column.flex+'">{[this.getRenderer('+i+',xindex)]}</div>');
            }

            if(column.tpl){ //Step 3
                column.tpl = new Ext.XTemplate(column.tpl);
            }
        }

        tpl = new Ext.XTemplate(html.join(''),{
            //Step 4
            getRenderer     : function(columnIndex,rowIndex){
                var column = columns[columnIndex], //Step 5
                    record = store.getAt(rowIndex);

                if(column.renderer){ //Step 6
                    return column.renderer.call(column.scope || me,record.get(column.dataIndex),record,columnIndex,rowIndex);
                }else if(column.tpl){ //Step 7
                    return column.tpl.apply(record.data);
                }
                //Step 8
                return record.get(column.dataIndex);
            }
        });

        return {
            xtype   : 'dataview',
            store   : store,
            itemTpl : tpl
        };
    }
});
  1. En el primer paso tomamos la instancia del store, esta la vamos a usar mas adelante en repetidas ocasiones, así que tener una referencia a nivel de la función es buena idea.
  2. El segundo paso es el más importante, aquí estamos llamando la función getRenderer pasándole dos parámetros, el indice de la columna y el xindex, que es el indice por cada elemento en el store, es importante mencionar que para ejecutar código dentro de un template lo hacemos dentro de {[ y ]}, aquí podemos poner todo el código javascript que necesitemos, pero mi consejo es llamar a funciones dentro de este template, debemos tratar de evitar definir grandes cantidades de código porque se podría poner muy feo eso.
  3. En el tercer paso estamos compilando el template de las columnas que tienen la propiedad tpl definida, es importante mencionar que esto solo se ejecutará una sola vez cuando se crea el grid, así que este es un buen lugar para crear cada template para luego usarlo al renderizar el contenido de las celdas.
  4. En el cuarto paso definimos un objeto como uno de los parámetros del constructor del template, dentro de este objeto podemos poner las funciones o inclusive propiedades que necesitemos acceder dentro del template, es por eso que aquí definimos la función getRenderer que recibe los parámetros columnIndex y rowIndex.
  5. En el quinto paso tomamos la columna usando el indexColumn y el record que se está iterando usando el rowIndex, recordemos que esta función se ejecutará por cada celda en cada row del grid.
  6. En el sexto paso verificamos si la columna tiene definido la propiedad renderer, de ser así ejecutamos la función pasandole  4 parámetros, algo interesante de este paso es que estamos dando oportunidad de ejecutar esta función en el scope de manera dinámica, si no esta definida la propiedad scope en la columna simplemente ejecutamos la función sobre el mismo grid.
  7. El séptimo paso solo se ejecutará si el sexto paso no fue ejecutado y en la columna que se esta renderizando se definió un template, aquí simplemente aplicamos el template con la información que tenemos en el record, esto nos permitirá poder usar todos los campos del record en el template, dándonos la flexibilidad de concatenar campos o hacer lo que se nos ocurra.
  8. El octavo paso solo se ejecutará si no fue definido un template ni la función renderer, entonces simplemente regresamos el valor del campo en esa columna.

Hay varios pasos en este último ejemplo, no quise separarlos porque podría ser un poco confuso, pero con esos cambios si probamos nuestra app en un navegador webkit o en el simulador de ios veremos algo como la siguiente imagen, también veremos que el precio aumentó un 10%.

Sencha Touch Templates

Sencha Touch Templates

Como se puede observar, el uso de templates es indispensable cuando se hacen componentes personalizados, claro está que todavía nos hace falta aplicar los estilos con CSS pero el DOM ya lo tenemos listo.

Ya que usamos un dataview tenemos todos los eventos necesarios con el contenido, no así con el título de las columnas, en el siguiente tutorial definiremos algunos eventos en las columnas para darle más flexibilidad a este componente.

Si has venido utilizando GIT es momento de guardar nuestros cambios en el historial.

$ git add .
$ git commit -m 'Adding a custom template to the columns'

Experimenta

Te recomiendo que experimentes un poco agregando nuevos templates a las columnas, definiendo la función renderer y probando diferentes variaciones.

Recuerda que puedes descargar el código fuente que contiene únicamente las carpetas app y packages, si has venido siguiente el curso ya sabrás que solo las tienes que remplazar en el proyecto que hicimos con el Sencha Command al inicio de este curso. También puedes probar el demo de este tutorial usando un navegador webkit.

Te gustaría recibir más tutoriales como este en tu correo?

Este tutorial pertenece al curso Tu primera app con Sencha Touch, te recomiendo revises el resto de los tutoriales ya que están en secuencia de menor a mayor complejidad.

Si deseas recibir más tutoriales como este en tu correo te recomiendo registrarte al curso, si ya eres miembro solo identifícate y registrate al curso, si no eres miembro te puedes registrar gratuitamente!

Si no gustas registrarte en este momento no es necesario! Aún así puedes recibir los nuevos tutoriales en tu correo! Jamás te enviaremos Spam y puedes cancelar tu suscripción en cualquier momento.

¿Olvidaste tu contraseña?

1Comentario

Instructor del curso

Crysfel3

Autor: Crysfel Villa

He desarrollado varias aplicaciones con Sencha Touch, algunas las puedes encontrar en el App Store de apple.

Descarga Código Fuente Ver Demostración

Regístrate a este curso

Este tutorial pertenece al curso Tu primera app con Sencha Touch, revisa todos los tutoriales que tenemos en este mismo curso ya que están en secuencia y van de lo más sencillo a lo más complicado.

Ya que este curso no está finalizado al registrarte podrás recibir en tu correo los nuevos tutoriales de este curso!

Tendrás acceso a descargar los videos, códigos y material adicional.

Podrás resolver los ejercicios incluidos en el curso así como los Quizzes.

Llevarás un registro de tu avance.