Blog

¿Qué es un store y cómo funciona?

Apr 21, 2009 | Español | By Crysfel | 10 Comments | Read in English

El tema de hoy es fundamental ya que el objeto Store es utilizado por los componentes que necesitan comunicarse con el servidor para mostrar la información, en este tema daré un vistazo rápido a lo más importante de este componente.

¿Qué es un store y cómo funciona?
Author: Crysfel

I'm a software developer with 6+ years of experience, when I'm not developing software I may be writing a tutorial, you can follow me on twitter

Un Store es un componente que almacena temporalmente información mediante registros, es utilizado como caché. Es importante mencionar que el Store contiene a otro componente capaz de leer e interpretar la información recibida, este lector es configurado antes de solicitar la información local o al servidor.

Material de apoyo

Para este tema el material de apoyo es un HTML y un JS donde estaremos trabajando, así que es necesario descargarlo y copiarlos dentro de la carpeta “ajax” que creamos en el tema anterior la cual está dentro de la carpeta “curso” en el servidor Web que instalamos en el primer capítulo de este curso.

Encapsulando el tutorial

Antes de comenzar con el ejemplo tenemos que encapsular el código que estaremos escribiendo para evitar coaliciones.

//El namespace para este tutorial
Ext.ns('com.quizzpot.tutorial');

com.quizzpot.tutorial.Store = {
	//Información dummy irá aquí	

	init: function(){
		//esto será ejecutado cuando el DOM esté listo
//crear el store aquí

		//cargar la información en el store aquí

		//crear los “listeners” de los botones aquí
	}

	//crear el método "orderAsc" aquí

	// crear el método "orderDesc" aquí

	// crear el método "filter" aquí

	// crear el método "query" aquí

	// crear el método "count" aquí

	// crear el método "find" aquí

	// crear el método "log" aquí
}
//disparamos la función “init” cuando el DOM esté listo
Ext.onReady(com.quizzpot.tutorial.Store.init,com.quizzpot.tutorial.Store);

He comentado el lugar donde escribiremos el código del tutorial, con la intención de que tengas una idea global de la estructura final del código.

La información

Para este ejemplo vamos a tomar la información de un arreglo, es importante mencionar que debemos crear un arreglo bidimensional el cual será “procesado” por el store que crearemos más adelante, este arregló estará al inicio del objeto “com.quizzpot.tutorial.Store” de la siguiente manera:

data: [ //información dummy para el ejemplo
	[1,'Crysfel','Software developer','m',25],
	[2,'Sasha','Figure skater','f',23],
	[3,'Jack','Software Architect','m',35],
	[4,'John','Javascript developer','m',24],
	[5,'Sara','Tester','f',31]
],

La información está contenida en un arreglo el cual contiene otros arreglos con la información, cada arreglo interno será un registro donde la posición cero es el “identificador” del registro, la posición uno es el “nombre” de una persona, la posición dos la “ocupación”, la posición tres es el “género” de la persona y la posición número cinco es la “edad”.

Crear un Store con información local

Ahora vamos a crear un “SimpleStore” con el que estaremos trabajando en este tutorial, esto lo hacemos de la siguiente manera:

//creamos una instancia del SimpleStore
this.store = new Ext.data.SimpleStore({
	fields: [ //definimos los campos que tendrá...
		{name:'name',mapping:1}, //cada registro...
		{name:'occupation',mapping:2}, // y lo relacionamos...
		{name:'gender',mapping:3},// con una posición en el...
		{name:'age',mapping:4}//arreglo que tiene la información
	],
	id: 0 //definimos la posición del ID de cada registro
});

Hasta este punto hemos creado el store, aún no tiene información pero ya es capaz de leer el arreglo que definimos anteriormente, la propiedad “fields”, que esta en la configuración del store, es donde se define el nombre de las propiedades de los registros mediante la propiedad “name” y se relaciona al arreglo con la información mediante la propiedad “mapping”, en este caso la propiedad mapping se le asigna la posición en el arreglo de donde sacará su contenido.

Cargar la información en el Store

Introducir la información en el Store es muy fácil ya que estamos usando información local contenida en un arreglo. Para que el store pueda consumir el arreglo definido lo hacemos de la siguiente manera:

//cargar la información del arreglo
this.store.loadData(this.data);

Si todo ha salido bien ya podremos usar la información contenida en el store.

Crear los “listeners” de los botones

Lo siguiente que haremos es crear los “listeners” del evento clic de cada botón que hay en el documento html.

Ext.fly('personBtn').on('click',this.find,this);
Ext.fly('txt').on('keyup',function(event,cmd){
	if(event.getKey() === event.ENTER){ //cuando sea la tecla ENTER
		this.find(); // realizamos la búsqueda
	}
},this);
Ext.fly('ascBtn').on('click',this.orderAsc,this);
Ext.fly('descBtn').on('click',this.orderDesc,this);
Ext.fly('older2030Btn').on('click',this.query,this);
Ext.fly('older30Btn').on('click',this.filter,this);
Ext.fly('countBtn').on('click',this.count,this);

El código anterior ya es familiar para nosotros, de no ser así te recomiendo darle un repaso a los temas anteriores donde se habló al respecto, lo más importante a resaltar es que las funciones que se han asignado a cada evento no las hemos definido.

Ordenar los registros

Ordenar la información es muy importante, y podemos hacerlo de una manera muy sencilla utilizando el método “sort”.

, //nota la coma separadora XD

orderAsc: function(){
	this.store.sort('name','ASC'); // ordenar en forma ascendente
	this.store.each(function(record){//por cada registro...
		this.log(record.get('name')); //imprime la propiedad “nombre”
	},this);
	this.log('___________________________________');
}, // <--- esta coma es importante

orderDesc: function(){
	this.store.sort('name','DESC'); //Ordenar en forma descendente
	this.store.each(function(record){ // por cada registro...
		this.log(record.get('name')); //imprime la propiedad “nombre”
	},this);
	this.log('___________________________________');
}

El método “sort” recibe como primer parámetro la propiedad por la que serán ordenados los registros y como segundo parámetro el tipo de orden, ascendente o descendente; una vez que se han ordenado se pueden recorrer los registros utilizando el método “each” del store, el cual itera sobre los registros.

El método “log” no ha sido definido aún, lo haremos más adelante, por ahora puedes poner un “console.debug” para imprimir en la consola de Firebug.

Filtrar registros en el store

En ocasiones es necesario filtrar la información contenida en el Store dependiendo algún criterio dado, en este ejemplo voy a realizar un filtro de las personas cuya edad sea mayor de 30 años; esto lo haré utilizando el método “filterBy”.

, // <--- La coma separadora

filter: function(){
	//filtrar a las personas...
	this.store.filterBy(function(record,id){
		return record.get('age') >= 30; //mayores a 30 años
	});

	//por cada registro...
	this.store.each(function(record){
		//imprimir en el “log”
		this.log(record.get('name')+' is older than 30 '+(record.get('gender')=='f'?'she':'he')+' is '+record.get('age'));
	},this);
	//limpiar los filtros
	this.store.clearFilter();
	this.log('___________________________________');
}

El método “filterBy” acepta como primer parámetro una función que será ejecutada por cada registro del store, ahí es donde se ha definido la condición deseada (edad mayor a 30 años), cuando la función retorne “true” el registro será tomado en cuenta y cuando retorne “false” el registro será descartado.

Luego de aplicar el filtro al store se ejecuta la función “each”, es importante mencionar que la función “each” únicamente será ejecutada sobre los registros que han sido filtrados anteriormente ya que se le ha aplicado un filtro al store.

Por último mediante la función “clearFilter” se limpian los filtros aplicados al store, permitiendo que todos los registros puedan ser utilizados nuevamente.

Buscar registros

El método anterior nos proporciona un manera de buscar registros descartando los registros que no necesitamos, el método “queryBy” hace algo semejante pero la diferencia es que regresa los registros encontrados en una colección, esto nos puede ser más útil o quizás más claro que el método anterior.

,//<--- La coma separadora

query: function(){
	//buscar gente mayor a 20 y menor que 30 años
	var collection = this.store.queryBy(function(record,id){
		return record.get('age') >20 && record.get('age')<30;
	});

	//por cada item en la colección
	collection.each(function(item,index){
		//imprime su nombre y edad
		this.log(item.get('name')+' is '+item.get('age')+ ' and '+(item.get('gender')=='f'?'she':'he')+' is younger than 30');
	},this);
	this.log('___________________________________');
}

Como puedes notar es muy semejante (por no decir igual) que el método anterior, la única diferencia es que regresa una colección con los registros que cumplen la condición especificada.

Buscar por una propiedad

Si queremos buscar un registro único podemos utilizar el método “find” el cual recibe como primer parámetro la propiedad sobre la cual queremos realizar la búsqueda, como segundo parámetro recibe un “String” o una expresión regular con el criterio de búsqueda, el tercer parámetro es opcional y es el número de registro donde comenzará a realizar la búsqueda, en el cuarto parámetro que también es opcional definimos si la búsqueda será ejecutada en cualquier parte del texto y el quinto parámetro define si queremos que ignore las mayúsculas y minúsculas.

//propiedad: name
//value: Crys
//comienza en: 0
//sobre cualquier parte del valor del registro
//no toma en cuenta mayúsculas y minúsculas
this.store.find('name', 'Crys',0,true,false);

Lo que regresa el método “find” es el índice donde encuentra la primera coincidencia, en caso de no encontrar nada regresará un “-1”.

,

find: function(){
	//tomamos lo que se introdujo en la caja de texto
	var value = Ext.fly('txt').getValue();
//si no hay nada salimos de esta función
	if(Ext.isEmpty(value)) return;
	//realizamos la búsqueda sobre la propiedad “name”
	var index = this.store.find('name',value,0,true,false);
	//si en encontró algo
	if(index>=0){
		//tomamos el registro por medio del índice...
		var record = this.store.getAt(index);
		//e imprimimos la información encontrada
		this.log(record.get('name')+' work as a '+record.get('occupation')+' and '+(record.get('gender')=='f'?'she':'he')+' is '+record.get('age')+' years old');
	}else{
		//si nada fue encontrado se le avisa al usuario
		this.log('<strong>'+value+' not found!</strong>');
	}
}

Puedes ver que se ha utilizado el método “getAt” para tomar el registro completo dándole el índice que necesitamos.

Si sabemos el ID del registro podemos sacarlo inmediatamente utilizando el método “getById”, lo que vamos a hacer es verificar si el usuario introdujo un número en la caja de texto, de ser así utilizaremos el ID, si es texto entonces ejecutaremos el código anterior.

, //<---

find: function(){
	//tomamos lo que se introdujo en la caja de texto
	var value = Ext.fly('txt').getValue();
//si no hay nada salimos de esta función
	if(Ext.isEmpty(value)) return;
	//si el valor es númerico
	if(/^\d+$/.test(value)){
		//buscamos por ID
		var record = this.store.getById(value);
		if(!Ext.isEmpty(record)){
			//si se encontró algo se imprime
			this.log(record.get('name')+' work as a '+record.get('occupation')+' and '+(record.get('gender')=='f'?'she':'he')+' is '+record.get('age')+' years old');
		}else{
			//si nada fue encontrado se avisa al usuario
			this.log('<strong>Record with id: '+value+' was not found!</strong>');
		}
	}else{
		//realizamos la búsqueda sobre la propiedad “name”
		var index = this.store.find('name',value,0,true,false);
		//si en encontró algo
		if(index>=0){
			//tomamos el registro por medio del índice...
			var record = this.store.getAt(index);
			//e imprimimos la información encontrada
			this.log(record.get('name')+' work as a '+record.get('occupation')+' and '+(record.get('gender')=='f'?'she':'he')+' is '+record.get('age')+' years old');
		}else{
			//si nada fue encontrado se le avisa al usuario
			this.log('<strong>'+value+' not found!</strong>');
		}

	}
}

El código anterior decide si la búsqueda será realidad por ID o por la propiedad especificada (en este caso “name”).

Contar los registros del store

Para contar los registros que actualmente están en el store es muy fácil, únicamente utilizamos el método “getCount”.

,

count: function(){
	//imprime el total de registros
	this.log('<strong>Total records: '+this.store.getCount()+'</strong>');
}

Notar que este método solo regresa los registros que actualmente están en el store.

El Log

Por último vamos a definir el método “log” que hemos estado usando para desplegar los mensajes.

,

log: function(txt){
	var el = Ext.get('response'); // get the LOG
	el.select('p.newest').removeClass('newest'); // quitar la última actualización
	Ext.DomHelper.append(el,'<p class="newest">'+txt+'</p>'); //actualizar el log
	el.scrollTo('top',el.dom.scrollHeight); //scroll abajo
	el.select('p.newest').highlight('F5FC49',{duration:0.5}); //resaltar el ultimo mensaje
}

Lo que hicimos en el código anterior es tomar el nodo “response” y agregarle párrafos con el texto que recibe, luego hacemos que destelle en color amarillo.

Conclusiones

Es importante que sepamos como buscar información contenida en un store, ya que este componente es muy usado para manipular información, es fundamental conocerlo para una mejor comprensión del Framework.

En este tema vimos un store muy sencillo que toma la información de un arreglo definido con JavaScript, en el mundo real la información viene de una base de datos, de una servicio Web o de algún otro lugar, en los siguientes temas veremos como realizar esto.

Si tienes alguna duda o pregunta déjalas en los comentarios con gusto las responderé y recuerda seguirnos en Twitter para estar al tanto de las actualizaciones o bien inscribirte a las Feeds.

10 Responses to “¿Qué es un store y cómo funciona?”

  • Ronhead Apr 21, 2009

    Estan muy buenos los tutos a veces me sacan de apuros y otras aprendo nuevas cosas que hacer
    gracias
    quizzzzzzzpot

  • pablo Apr 22, 2009

    como siempre fantástico! y cada vez se pone mas interesante

  • Lord Tinchen Apr 23, 2009

    Muy bueno los tutoriales. Se logra entender perfectamente el tema. Te felicito!

  • Osvaldo Jul 19, 2009

    Realmente muy buenos los tutos. sin mucho rodeo todo claro y se entiende perfectamente. te felicito!

  • spit Jul 21, 2009

    En este tema se hecha de menos un videotuto… porque aqui ya hay conceptos algo mas liosos para comprender para alguien como yo que solo he programado en c++ en la universidad,de todas formas esta basntante bien y mas o menos se comprende todo…

  • Elías Manchón Aug 17, 2009

    Lo que me ha dejado descolocado ha sido la sentencia en javascript para testear el tipo de dato de la variable value, en concreto la línea que hace referencia a la siguiente expresión:

    if(/^\d+$/.test(value))

    Es la primera vez que veo eso.

    Salu2

    • Crysfel Aug 17, 2009

      Son expresiones regulares (RegExp) digamos que es un “mini” lenguaje que la mayoría de los lenguajes implementan (JAVA, PHP, Ruby, Javascript,etc…), es muy poderoso y te resuelve muchos problemas ;)

      saludos

    • Elías Manchón Aug 17, 2009

      si, he trabajado con expresines regulares pero no con esa sintáxis.

  • cfontes Sep 04, 2009

    Muy practicos, claros y sencillos los ejemplos; me han servido bastante, gracias…

  • daniel Oct 02, 2009

    Hola Crysfel muy bueno tu pagina pero necesito saber, bueno si es que puedes, lo que pasa es que necesito llenar un textfield desde un datastore, el campo que necesito trae el mismo dato en todas las tuplas, no se si me explique bien
    Saludos
    ADIOS

Leave a Reply







Updates

RSS

Subscribe to our feeds to receive updates of our newest posts and free tutorials.

Site search

Maybe we have what you need, would you like to search first?

Donations

Would you buy me a cup of coffee? I am sharing my knowledge and time with you, help this project grow. Thank you!