Blog

Guardar los cambios del Grid editable usando Ajax

Sep 03, 2009 | Español | By Crysfel | 25 Comments

En el tutorial de hoy veremos como guardar la información de un Grid editable utilizando el componente Ajax que viene con el Framework, también mostraré como agregar nuevos registros al Grid y guardarlos en el servidor.

Guardar los cambios del Grid editable usando Ajax
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

En tutoriales anteriores hemos visto como crear un Grid con capacidad de editar las celdas mediante una caja de texto o un Combobox, pero realmente eso no nos sirve de mucho si no guardamos esos cambios en nuestro servidor, el día de hoy voy a mostrar la manera tradicional de guardar estos cambios.

Es importante mencionar que en Ext 3 hay una manera más sencilla de hacer esto (utilizando un “Writter”), pero quiero mostrar el método “tradicional” que usábamos en la versión de Ext 2 porque creo que es importante para tener una compresión clara de lo que sucede ya que en futuros tutoriales mostraré una forma más sencilla.

Material de apoyo

Para comenzar es necesario descargar el material de apoyo que consta de un archivo HTML donde únicamente se importa el Framework y hay clases “CSS” definidas, también encontrarás un archivo “JS” donde he definido el “namespace” y además algunos métodos que implementaremos en este tutorial, viene también un archivo “PHP” el cual nos servirá para simular el guardado y actualizado de información y por último una carpeta “icons” que contiene unas imágenes que mostraremos en los botones.

Demostración

He preparado una demostración de lo que haremos al término de este tutorial, te invito a que la pruebes por ti mismo.

Grid editable

Demostración

Guardar la información en el servidor

Para hacer más sencillo este ejemplo no voy a guardar la información en una base de datos, pues he de suponer que sabes como hacerlo así que voy a utilizar las “sesiones” para simular que guardamos y actualizamos la información, el código para lograr esto es el siguiente:

<?php
	header("Content-Type: text/plain");
	session_start(); 

	$add = $_POST['records'];

	if(!isset($_SESSION['data'])){
		$data = array( //creates the initial data
			'success'=>true,
			'total'=>11,
			'data'=>array(
				array('id'=>1,'name'=>'John doe','age'=>23,'country'=>'USA'),
				array('id'=>2,'name'=>'Taylor Swift','age'=>19,'country'=>'USA'),
				array('id'=>3,'name'=>'Carlos Mena','age'=>22,'country'=>'México'),
				array('id'=>4,'name'=>'Christiano Ronaldo','age'=>24,'country'=>'Portugal'),
				array('id'=>5,'name'=>'Sasha Cohen','age'=>25,'country'=>'USA'),
				array('id'=>6,'name'=>'Christian Van Der Henst','age'=>27,'country'=>'Guatemala'),
				array('id'=>7,'name'=>'Collis Ta\'eed','age'=>31,'country'=>'USA')
			)
		);
		$_SESSION['data'] = $data; //load the data in sessions for the first time
	}else{
		$data = $_SESSION['data']; //get the data if exist in session
	}

	if(isset($add)){ //if there are records to insert/update
		$records = json_decode(stripslashes($add)); //parse the string to PHP objects
		$ids = array();
		foreach($records as $record){
			if(isset($record->newRecordId)){ //records to insert
				$id = count($data['data']);
				$info = array(
					'id'=> id,
					'name'=> $record->name,
					'age'=> $record->age,
					'country'=> $record->country
				);

				array_push($data['data'],$info); //add the new record to session
				array_push($ids,array('oldId'=>$record->newRecordId,'id'=>$id));//new id
			}else{ //records to update
				foreach($data['data'] as $key=>$r){ //search the record to update
					if($r['id'] == $record->id){
						$data['data'][$key]['name'] = $record->name; //update the properties
						$data['data'][$key]['age'] = $record->age;
						$data['data'][$key]['country'] = $record->country;
						break;
					}
				}
			}
		}

		//print the success message
		echo json_encode(array(
				'success'=>true,
				'data'=>$ids
			));
	}else{
		//print all records in session
		echo json_encode($data);
	}
?>

He comentado los puntos más importantes en el código, recuerda que es solo un ejemplo, en el mundo real deberías guardar la información en una base de datos o enviarlas a un WebService, etc. cuando implementes tu “controller” debes tener en cuenta que éste debe hacer dos cosas (por ahora).

  • Si recibe registros (mediante el parámetro “post” llamado “records”) debe insertarlos o actualizarlos, esto depende de la variable “newRecordId” ya que si existe nos indica que es un registro nuevo y tiene que insertarse de lo contrario es un registro existente y tiene que actualizarse.
  • Si no recibe registros solamente debe desplegar los registros que existen.

Creación del Grid editable

En este momento vamos a crear el Grid editable con los campos que definimos en el código anterior; escribiremos en el método “init” el siguiente código:

init: function(){
		//main code
		//creates the store for the grid
		var store = new Ext.data.JsonStore({
			url: 'editorgrid-ajax.php',
			root: 'data',
			id:'id',
			fields: ['name','age','country']
		});
		//load the data
		store.load();

		//creates the texfield to edit the data
		var textField = new Ext.form.TextField();
		var numberField = new Ext.form.NumberField({allowBlank:false});
		//creates the editor grid
		this.grid = new Ext.grid.EditorGridPanel({
			store: store,
			columns: [
				new Ext.grid.RowNumberer(),
				{header:'Name', dataIndex:'name',sortable: true,width:145,editor:textField},
				{header:'Age', dataIndex:'age',sortable: true, editor:numberField},
				{header:'Country', dataIndex:'country',sortable: true, editor:textField}
			],
			border: false,
			stripeRows: true
		});

		//creates a window to hold the grid
		var win = new Ext.Window({
			title: 'Editor Grid example',
			layout: 'fit',
			width: 410,
			height:350,
			items: this.grid
		});
		//show the window and the grid
		win.show();
	},

No me detendré a explicar el código anterior pues ya lo hice en los tutoriales anteriores, así que si no tienes idea de lo que pasó, te recomiendo comenzar con los tutoriales pasados.

Hasta ahora deberíamos ver en pantalla algo como la siguiente imagen:

Grid editable

Grid editable

Guardar los registros modificados

Ahora si viene la parte interesante de este tutorial, pero primero necesitamos crear un botón para que al ser presionado por el usuario enviemos la información al servidor mediante Ajax, también vamos a crear un “ToolBar” donde estarán los botones que usaremos.

var win = new Ext.Window({
	title: 'Editor Grid example',
	tbar:{
		defaults:{scope:this},
		items:[
			{text:'Save changes',iconCls:'save-icon',handler:this.save}
		]
	},
	layout: 'fit',
	width: 410,
	height:350,
	items: this.grid
});

Grid editable

Toobar en la ventana contenedora

Solamente quiero hacer notar que mediante la propiedad “handler” definimos la función que se ejecutará cuando el usuario de clic sobre el botón, además mediante la propiedad “default” podemos aplicar la propiedad “scope” a todos los botones que definamos, es importante definir el “scope” para la correcta ejecución de la función.

Dentro de la función “save” escribiremos el siguiente código:

//save changes in the grid
var modified = this.grid.getStore().getModifiedRecords();//step 1
if(!Ext.isEmpty(modified)){
	var recordsToSend = [];
	Ext.each(modified, function(record) { //step 2
		recordsToSend.push(Ext.apply({id:record.id},record.data));
	});

	this.grid.el.mask('Saving…', 'x-mask-loading'); //step 3
	this.grid.stopEditing();

	recordsToSend = Ext.encode(recordsToSend); //step 4

	Ext.Ajax.request({ 		// step 5
		url : 'editorgrid-ajax.php',
		params :{records : recordsToSend},
		scope:this,
		success : function(response) { //step 6
			this.grid.el.unmask();
			this.grid.getStore().commitChanges();
		}
	});
}

En el paso 1 se recogen los registros que han sido modificados, esto nos regresa un arreglo con cada “record” que se modificó, luego verificamos que no este vacío.

En el paso 2 iteramos el arreglo de registros modificados y vamos agregándolos a un arreglo que se llama “recordsToSend” en formato JSON, además incluimos el “id” ya que éste no se encuentra con el resto de la información.

En el paso 3 le ponemos una máscara al Grid con el mensaje de “Saving…” y le agregamos la clase CSS “x-mask-loading” la cual muestra una animación que denota que se esta procesando algo. Mediante el método “stopEditing” nos aseguramos que el usuario no este editando ningún otro campo.

En el paso 4 transformamos el “Array” a “String” para ser enviado al servidor en formato JSON.

En el paso 5 realizamos la petición al servidor por medio de Ajax, definimos la “url” que invocaremos así como la información que se enviará en el parámetro “records”, recuerda que cuando enviamos información utilizando la propiedad “params” la petición se realiza por el método “post” por defecto.

En el paso 6 definimos una función que se ejecutará cuando el servidor responda, dentro de esta función quitamos la máscara que cubría el Grid y hacemos un “commit” de los cambios ocurridos en el Grid, al hacer este “commit” los campos marcados como “sucios” (Dirty) dejarán de serlo.

Grid editable

Editando el contenido de las celdas

Grid editable

Enviando la información al servidor para ser guardada

Grid editable

La información ha sido guardada correctamente

Crear un registro nuevo

En la sección anterior logramos guardar los registros que fueron modificados por el usuario, ahora vamos a insertar nuevos registros en el Grid, para esto necesitamos crear un botón en la barra de herramientas que nos permita realizar lo antes mencionado.

var win = new Ext.Window({
	title: 'Editor Grid example',
	tbar:{
		defaults:{scope:this},
		items:[
			{text:'Save changes',iconCls:'save-icon',handler:this.save},
			{text:'Add Person',iconCls:'add-icon',handler:this.add} // add button
		]
	},
	layout: 'fit',
	width: 410,
	height:350,
	items: this.grid
});

Ahora necesitamos implementar el método “add” que está invocando el botón cuando es presionado.

//add a new row to the grid
var position = this.grid.getStore().getCount();
var id = Ext.id();
var defaultData = {	//step 1
	newRecordId: id
};
var Person = this.grid.getStore().recordType; //step 2
var person = new Person(defaultData,id);
this.grid.stopEditing(); //step 3
this.grid.getStore().insert(position, person); // step 4
this.grid.startEditing(position, 1); //step 5

El código anterior debe ser escrito dentro del método “add”.

En el paso 1 se crea un objeto con la información por defecto, en este caso únicamente se está definiendo la propiedad “newRecordId” la cual es utilizada por el servidor para saber si el registro lo debe insertar o actualizar en la base de datos, el valor de esta propiedad ha sido generado mediante “Ext.id()” para tener un id único.

El paso 2 es muy importante y es necesario porque cuando creamos el Store del grid nosotros no definimos ni el “Reader”, ni el “Record” directamente, esto lo hizo “Ext” automáticamente, por lo tanto no tenemos una referencia al “Record” generado, gracias a la propiedad “recordType” del “store” accedemos al “Record” que fue creado por el Framework dinámicamente, una vez que tenemos la referencia al componente “Record” creamos una instancia de éste con la información que generamos en el paso 1 y le asignamos su “id”.

En el paso 3 solamente detenemos cualquier edición activa por parte del usuario.

El paso 4 es el que hace la “magia”, ya que es aquí donde se inserta el nuevo “record” al store del Grid y automáticamente se reflejará la nueva fila vacía en el Grid, el primer parámetro que recibe este método es la posición donde queremos que se inserte, la posición la hemos calculado previamente contando el total de filas existentes esto nos da como resultado que la fila se inserte hasta el final del grid.

En el paso 5 solamente hacemos que de la fila que acabamos de insertar en la columna número “1” aparezca una caja de texto (que definimos al crear el Grid) para editar el contenido de la celda, es importante mencionar que la columna “0” para este caso es la columna donde están los números, en caso de no tener esta columna podríamos comenzar a editar la columna “0”.

Al actualizar nuestro explorador debería ver algo como la siguiente imagen en la pantalla:

Grid editable

Agregando una fila al Grid

Para guardar la información que insertemos en el registro nuevo no tenemos que hacer nada puesto que ya se debería guardar utilizando el método “save” que hicimos anteriormente.

Grid editable

Guardando él registro nuevo

Si has notado se esta enviando al servidor el registro a insertar con la propiedad “newRecordId”, además el “id” asignado no es el mismo “id” que le asigna el servidor, esto lo sabemos porque en la respuesta el servidor nos dice el “id” que recibió y el “id” que asignó.

Grid editable

Parámetros enviado al servidor por Ajax

Lo que debemos hacer ahora es modificar el método “save” para que sincronice los “id’s” correctamente. Dentro de la función “success” escribiremos el siguiente código:

//update the records with the correct ID's
var info = Ext.decode(response.responseText); // step 1
Ext.each(info.data,function(obj){
	var record = this.grid.getStore().getById(obj.oldId); //step 2

	record.set('id',obj.id); //step 3
	delete record.data.newRecordId; //step 4
},this);

En el paso 1 se está decodificando la información que nos regresó el servidor en formato JSON para poder manipularla fácilmente.

En el paso 2 se obtiene el “Record” utilizando el “id” que le fue asignado a la hora de crearlo.

En el paso 3 se actualiza su “id” por el “id” asignado por el servidor en nuestra base de datos.

El paso 4 es importante para eliminar la propiedad “newRecordId” que tiene el registro, de esta forma evitamos que se inserte nuevamente si solamente queremos actualizarlo.

Cancelar los cambios

Por defecto al editar el contenido de las celdas de un Grid éstas quedan en un estado de “Dirty”, en este estado nosotros podemos deshacer los cambios y regresar a la información original.

Primero creamos el botón que nos permitirá realizar la acción pertinente.

var win = new Ext.Window({
	title: 'Editor Grid example',
	tbar:{
		defaults:{scope:this},
		items:[
			{text:'Save changes',iconCls:'save-icon',handler:this.save},
			{text:'Add Person',iconCls:'add-icon',handler:this.add},
			{text:'Cancel changes',iconCls:'cancel-icon',handler:this.cancel} //cancel changes
		]
	},
	layout: 'fit',
	width: 410,
	height:350,
	items: this.grid
});

Grid editable

Botón para cancelar los cambios

Luego implementamos el método “cancel” de la siguiente manera:

cancel: function(){
	//cancel the changes in the grid
	this.grid.getStore().rejectChanges();
}

Cuando invocamos el método “rejectChanges” del store, automáticamente regresan al estado original las celdas modificadas, esto es suficiente para deshacer los cambios ocurridos.

Conclusiones

En este tutorial aprendimos como guardar información a través de Ajax, también como insertar y actualizar los registros de un store y verlos reflejados en un Grid editable, en futuros tutoriales mostraré como hacerlo de una manera más sencilla utilizando las nuevas características de Ext 3.

Si tienes alguna duda o sugerencia puedes hacerlo en los comentarios, recuerda que tenemos un foro donde la comunidad está creciendo y la participación es muy buena, te invito también a seguirnos en Twitter (@quizzpot) para estar al tanto de las actualizaciones del sitio.

25 Responses to “Guardar los cambios del Grid editable usando Ajax”

  • Jurasec Sep 04, 2009

    Gracias.

  • Pedro Sep 11, 2009

    La verdad es que son excelentes estos tutoriales. Gracias por el tiempo que te tomas al armarlos, en cuanto pueda voy a reconocer tu esfuerzo con algunos cafes.

    Gracias !!!

  • DarkAngel Sep 21, 2009

    Realmente estoyinteresado en el Writter algún ejemplo para orientarme,he visto la documentacion de ext pero no termino de entenderlo

  • duvan1124 Oct 07, 2009

    Hola amigos… excelente ejemplo pero como seria un ejemplo para guardar la informacion en la base de datos.. les agradesco mucho por su ayuda ya que recien estoy empezando a trabajar con esta gran libreria.. gracias

    • Crysfel Oct 07, 2009

      Para gusardar los cambios solamente necesitas tomar el parámetro en el servidor, convertir el JSON en objetos que puedas usar en el lenguaje de tu servidor y hacer un insert en la base de datos.

      saludos

  • aur19 Oct 15, 2009

    puedes colocar el codigo para guardar en la base de dsatos por favor??

  • jairo Oct 19, 2009

    Buen dia señores, pienso que los tutoriales son muy completos, pienso que estan muy bien explicados y enfocados en ext-js.

    En mi opinion, y me disculpan, pedirle que nos ponga un ejemplo completo es desviarnos del tema, ya que esto tiene que ver con sql y el lenguaje que se utiliza, llamese java, php, phyton, etc.

    Seria mejor de investigar por otro lado y centrarnos en lo que nos interesa, ext-js.

    Gracias.

  • Yovanis Nov 30, 2009

    Hola, sip Excelente!!!

    Gracias !!!

  • nauricio Dec 03, 2009

    crysfel, seria de gran ayuda u ejemplo de como hacer el update y el insert en el archivo php, favor tu ayuda

    • Crysfel Dec 07, 2009

      Eso es muy sencillo, y existen cientos de tutoriales al respecto ;) solamente usa las funciones que proporciona PHP para el manejo de base de datos, googlea un poco y encontrarás miles de ejemplos.

  • Eric Dec 11, 2009

    No seamos flojos y busqeumos un poco, como dice el sabio Crysfel, en googel teclea PHP + MySQL y saldran miles de links y en español. Una pregunta (espero no sea demasiado obvia).

    Crysfel: Como puede solo enviar al servidor los campos modificados y no toda la fila? es posible con lo que has mostrado hasta el momento?

    • Crysfel Dec 14, 2009

      Puedes hacerlo mediante “Ext.Ajax.request” enviando unicamente los campos que necesites, para ver si han sido modificados un registro revisa la propiedad “phantom” de cada record.

      saludos

  • Raul Suarez Jan 15, 2010

    Que buen tutorial, muchas gracias

  • Vinnie Feb 23, 2010

    Buen aporte, solo comentar que respeta la licencia de WP sobre el footer, se ve feo en un desarrollador quitar los creditos, suerte.

  • camilo Feb 23, 2010

    me funciona perfectamente excepto que al momento de presionar otro registro(add person), en los nuevos campos me arroja basura al momento de hacer doble click(editarlos). me podrias ayudar?

  • Diego Gonzales Soto Feb 26, 2010

    Hola Crysfel un gusto poder visitar nuevamente tu pagina de extJS, bueno tengo una pregunta amigo como puedo hacer un seleccionador de idiomas para mis aplicaciones echas en extjs, ejemplo que el usuario pueda elegir su propio idioma o elegir el idioma que el guste esto en un datagrip que tenga incorporado una opcion donde yo usuario pueda seleccionar el idioma que guste, esta aplicacion debera cambiar su idioma al idioma elegido,

    ya q en la libreria de estJS tenemos una carpeta q contiene muchos idiomas en la ruta src/locale/ en este lugar se encuentra varios idiomas bueno yo solo quiero q elegir tres idiomas español, ingles, portuges, para el ejemplo como lo puedo hacer esto una ayudita por favor como hacer este seleccionador de idiomas.

  • Diego Cartes Apr 07, 2010

    Muchas Gracias por compartir tus conocimientos, pero quiero solicitarte un favor, es posible que pongas un ejemplo de como seria en una base de datos?.
    Desde ya muchas Gracias..

  • Blackfire Apr 13, 2010

    Muchas gracias por el tutorial es de mucha ayuda pienso agregarle la opcion de eliminar un rejistro.

  • Juan Manuel Apr 17, 2010

    Y como manejas los errores??

  • SrCobranza Jul 02, 2010

    hola Crysfel necesito hacer una grilla editable pero en XML intente convertir tu codigo JSON a XML pero tube demaciadas complicaciones, te agradeceria poder hacerlo en XML atte. SrCobranza.

  • Ronhead Jul 08, 2010

    Excelente tutorial….le estaré revisando
    ojala me sirva para lo que estoy haciendo

    se agradece :)

  • Ronhead Jul 13, 2010

    tengo una duda!
    como hago para recuperar todos los registros?, no solamente los modificados?
    # //save changes in the grid
    # var modified = this.grid.getStore().getModifiedRecords();//step 1

    muchas gracias,, no he podido entender como recuperar Todos los datos de la grilla

  • raymundo Jul 15, 2010

    oye tengo una duda. por que al mometo de actualizar un dato no lo hace y me inserta uno nuevo, pero la actualizacion no la hace

  • raymundo Jul 20, 2010

    Tengo duda. por que al mometo de querer actualizar un dato me inserta otro?

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!