Aprendiendo Ext JS 3

Creando un Wizard Más videos

Descripción del tema

En esta ocasión veremos cómo podemos crear un Wizard, esto lo haremos utilizando un layout de tipo “Card” y un solo formulario, el wizard que simularemos recojerá la información necesaria para crear una conexión a una base de datos. En este tutorial veremos la manera de cambiar la información que queremos desplegar en una ventana, esto lo haremos usando un “CardLayout” el cual nos permite cambiar el contenido de una ventana sin tener que actualizar en nuestro explorador, la siguiente imagen el resultado que se obtendrá al final del tutorial.
resultado final

Resultado Final

Empaquetando el Tutorial

Vamos a empaquetar el código para evitar conflictos con otras variables o librerías que usemos en nuestro proyecto.
Ext.ns(“com.quizzpot.tutorial”);

com.quizzpot.tutorial.Wizard = {
	index	: 0,

	init : function(){
		//code here
	}
}
Ext.onReady(com.quizzpot.tutorial.Wizard.init,com.quizzpot.tutorial.Wizard);
Más adelante se explica la propiedad “index” que hemos definido dentro del objeto principal.

Creando el Cardlayout

Lo primero que haremos es crear un formulario el cual contendrá la información que deseamos desplegar a lo largo de nuestro wizard. Dentro de la función “init” colocaremos el siguiente código:
this.form = new Ext.FormPanel({	 // step 1
	layout	: "card",	 //step2
	border	: false,
	activeItem	: this.index, 	//step3
	items		: [this.createAllias(), this.createDriver(), this.createCredentials()] //step 4
});
En el paso uno solo hicimos una instancia del “FormPanel”. Lo interesante viene en el paso dos, a estas alturas del curso los layouts que más hemos usado son de tipo “fit” y ”border”, en esta ocasión usaremos uno de tipo “card”, este layout nos permite desplegar todos los “items” de esta instancia uno a la vez, además de proporcionarnos métodos para cambiar entre una “carta” y otra. En el paso tres lo que hacemos con “activeItem” es indicar cual objeto del arreglo de “items” será el que se usará cuando se inicie la aplicación, y si recordamos “index” es igual a cero con esto indicamos que queremos el objeto de la posición cero del arreglo “items”. En el paso cuatro al arreglo “items” le asignamos tres funciones “createAllias()”, “createDriver()” y por último “createCredentials()”, vamos a ir viendo en detalle cada una de estas funciones cuyo objetivo es crear la interface para cada paso del wizard.

Definición de los pasos en el Wizard

La primera función será nuestra primera pantalla en la cual debe aparecer un campo donde el usuario asignará un nombre a la conexión, también tendremos una pequeña descripción para asistir al usuario. La segunda función será la pantalla siguiente esta mostrará un combo en el cual el usuario seleccionará el servidor de base de datos, por ejemplo nuestro combo pude tener valores como: MySQL, Oracle Thin, SQL Server, Informix, etc. Esta información la obtendremos desde una tabla de una base de datos. La última función creará la última pantalla en la que se capturan las credenciales del servidor, vamos a desplegar algunos campos de texto y uno de tipo password. Por el momento podemos eliminar o comentar las últimas dos funciones, trabajaremos con ellas un poco más adelante.

Función “createAllias”

Como mencionamos antes, esta función lo único que contiene es una pequeña descripción y un formulario para obtener el nombre de la conexión, esto lo haremos de la siguiente manera:
createAllias : function(){
	return {
		xtype		: "panel",
		layout	: "form",
		border	: false,
		padding	: 10,
		items		: [ {html : "<h1>New Connection Wizard</h1> <br> “+
“<p>This Connection Wizard will guide you through the steps to setup a"+
"database connection. Make sure you have access to the required JDBC driver files(s) for the database you are"+
"going to access.<br>The information about supported databases and links to download sites for JDBC drivers are available"+
" at <a href="+"http://www.dbvis.com"+">http://www.dbvis.com</a></p><br><br>", border : false},

		{xtype     : "textfield", name : "alias"},
		{html       : "<p><br>Enter the connection alias for the new data base connection. This is the name you will use to refer this database"+
"connection throughout the application</p>", border : false}]
		
	};
}
Lo que hicimos es crear la función donde en el “return” creamos un panel (utilizando su “xtype”) el cual tiene un layout de tipo “form” esto es para que al definir el textfield pueda aparecer correctamente su “Label”, de lo contrario no aparecerá. Al panel que regresamos le podemos colocar todo lo que deseamos que aparezca en pantalla en el atributo “items”. Con esto tendríamos la primera pantalla lista pero no la podemos ver porque no se ha renderizado el formulario que la contiene. Para poder ver nuestra pantalla lo que haremos es crear una ventana que tendrá al “form” principal, también colocaremos los botones que usaremos para el cambio entre pantallas.
//step 1
this.backBtn = new Ext.Button({text : "Back",handler : this.back,scope : this,hidden:true});
this.nextBtn = new Ext.Button({text : "Next",handler : this.next,scope : this});
this.finishBtn = new Ext.Button({text : "Finish", hidden : true, handler:this.finish,scope:this});
		
this.win = new Ext.Window({
        title		        : "New Connection Wizard",
        layout		: "fit",
        width		        : 450,
        height		: 400,
	resizable	        : false, //step 2
	bodyCssClass	: "wizard-image", //step 3
	fbar		        : [this.backBtn,this.nextBtn,this.finishBtn], //step 4
	items		        : [this.form] //step 5
});
En el paso uno creamos los tres botones que usaremos para el cambio entre pantallas, si notamos los botones “backBtn” y “finishBtn” están ocultos (“hidden”) ya que a estos botones les daremos un uso especial más adelante, si lo deseas puedes comentar la propiedad “handler” ya que no hemos definido las funciones todavía, más adelante lo haremos. En el paso dos hacemos que no se puedan cambiar las dimensiones de la ventana. En el paso tres se asigna la clase CSS “wizard-image” al cuerpo de la ventana, esta clase coloca una imagen a la ventana, para esto es necesario definir la clase “wizard-image” en una hoja de estilos o en el documento HTML de la siguiente manera:
.wizard-image{background:transparent url(wizard.png) 10px center no-repeat;padding-left:150px;}
Nótese que se ha asignado un padding de 150px a la imagen, esto es para que se despliegue correctamente. En el paso cuatro se han asignado los botones al “footer bar” (fbar), esto permite posicionarlos en la parte inferior de la ventana. El paso cinco solamente le asignamos el formulario a la ventana como contenido principal. Por último es necesario renderizar los componentes que hemos creado, al usar una ventana solamente es necesario ejecutar el método “show” de la instancia “win”.
this.win.show();
Primera Pantalla

Primera Pantalla

Función “createDriver”

Lo siguiente es crear la función “createDriver” que usaremos para la siguiente pantalla como mencionamos antes en esta pantalla el usuario escoge los drivers que usará, esta información será obtenida desde nuestra base de datos y desplegada en un combo. Primero veremos la estructura de la base de datos.
-- phpMyAdmin SQL Dump
-- version 3.2.0.1
-- http://www.phpmyadmin.net
--
-- Servidor: localhost
-- Tiempo de generación: 19-10-2010 a las 03:58:23
-- Versión del servidor: 5.1.36
-- Versión de PHP: 5.3.0

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Base de datos: `test`
--

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `drivers`
--

CREATE TABLE IF NOT EXISTS `drivers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `database` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `driver` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

--
-- Volcar la base de datos para la tabla `drivers`
--
Tomando en cuenta la definición de la tabla anterior necesitamos exponer la información usando nuestro lenguaje favorito, para este tutorial usaremos PHP, pero bien pueden usar Java, Ruby, Grails o cualquier otro lenguaje.
<?php
	$link=mysql_connect("localhost", "root", "") or die ("Error conectando a la base de datos.");
	mysql_select_db( "test",$link) or die("Error seleccionando la base de datos.");

	$result=mysql_query("SELECT * FROM drivers");

	$drivers=array();
	while($row=mysql_fetch_array($result)){
		array_push($drivers,array(
			"id"		=>$row["id"],
			"database"	=>$row["database"],
			"driver"	=>$row["driver"]
			));
	}
	
	echo json_encode(
		array(
			"succsess"	=> true,
			"info"		=> $drivers
		)
	);
El resultado al ejecutar ese código será el siguiente:
{"succsess":true,"info":[{"id":"1","database":"MySQL","driver":"com.mysql.jdbc.Driver"},{"id":"2","database":"Oracle","driver":"oracle.jdbc.driver.OracleDriver"}]}
Ya que tenemos la información necesaria lo siguiente es crear el combo y el panel que tendrá la información para la desplegar en pantalla. Lo haremos de la siguiente manera:
createDriver : function(){
	//se crea el store
	var store = new Ext.data.JsonStore({ //step 1
		url	:"drivers.php", //archivo donde sacará la información
		root	: "info",
		fields	: [ //campos del store que usará
			{name :"id"},
			{name :"database", type : "string"},
			{name :"driver", type : "string"},
		]
	});

	//se crea el combo asignándole el store
	var combo = new Ext.form.ComboBox({ //step 2
		fieldLabel	        :"Database", 
		name		        :"database",
		forceSelection	: true, // esta opción obliga al usuario a seleccionar un valor del combo
		store		        : store, //asignándole el store
		emptyText	        :"pick one DB...", // texto mostrado antes de que se seleccione algo
		triggerAction	: "all", // indica que siempre muestre todos los datos de su store
		editable	        : false, // no se puede editar el contenido
		border		: false,
		width		        : 150,
		displayField	        : "database", //la información que mostrara dentro del combo
		valueField	        : "id" // lo que enviará al servidor
	});
		
	return { //step 3
		xtype		: "panel",
		layout	: "form",
		padding	: 10,
		labelWidth	: 60,
		border	: false,
		items		: [{html : "&lt;h1>Select Database Driver&lt;/h1>&lt;br>",border : false},
    combo,
				    {html : "<br><br><p>Select the appropriate database driver from the list above.</p>",border : false}]
	}
},
En el paso uno lo que hicimos fue crear el “store” que nos trae la información que obtenemos en el archivo driver.php, además de que lo configuramos para que pueda interpretar correctamente esa información. En el paso dos creamos el combo con la información que contiene el store, en el código he comentado algunas configuraciones usadas. En el paso tres creamos el panel con un layout de tipo ”form” y en “items” le pasamos lo que queremos que contenga este panel, en primer lugar ponemos una descripción usando el atributo “html” luego pasamos el combo y por último se ponen las indicaciones también con un atributo “html”. Con esto tendríamos la segunda pantalla que es parecida a esta.
segunda pantalla

Segunda pantalla

Función “createCredentials”

Por ultimo crearemos el formulario donde el usuario introduce el nombre del servidor, el puerto, la base de datos, el usuario y la contraseña, esto será muy similar a las funciones anteriores:
createCredentials : function(){
	return{
		xtype		: "panel",
		layout	: "form",
		labelWidth	: 100,
		padding	: 10,
		border	: false,
		items		: [{html : "<h1>Test</h1><br><br>", border : false},
				{fieldLabel : "Server",xtype : "textfield", name : "server"},
				{fieldLabel : "Port",xtype : "textfield", name : "port"},
				{fieldLabel : "Database",xtype : "textfield", name : "database"},
				{fieldLabel : "UserID",xtype : "textfield", name : "user"},
				{fieldLabel : "Password",xtype : "textfield", inputType : "password", name : "passwrd"},
				{html : "<br><br><p>Press the Finish button to create and connect this database connection.</p>", border : false}]
	}
},
Esta función básicamente funciona como las últimas dos. Lo que hacemos es crear el panel con un layout de tipo “form” y dentro de “items” colocamos lo que contendrá el panel, como lo que deseamos obtener es información que proporciona el usuario usamos “textfied” para que nos crea el campo donde el usuario podrá introducir la información, notemos que en el último “textfield” usamos “inputType” de tipo “password” con la finalidad de que este campo no muestre los caracteres alpha numericos ya que está destinado a para recibir una contraseña. Con esto tenemos la tercera pantalla:
terceara pantalla

Tercera pantalla

Avanzar en los pasos del wizard

Ya que tenemos nuestras pantallas listas lo siguiente es asignarle acciones a los botones que definimos al inicio del tutorial, descomenta la propiedad “handler” de cada botón. Para avanzar entre las pantallas crearemos la función “next”, de la siguiente manera:
next: function(){
	this.backBtn.show();	//step 1
	if(this.index < this.form.items.length-1){	//step 2
		this.index++;
		var cardlayout = this.form.getLayout();	//step 3
		cardlayout.setActiveItem(this.index);
	
		//step 4
		if(this.index == this.form.items.length-1){	//si esta en el ultima carta
			this.nextBtn.hide();
			this.finishBtn.show();
		}
	}
},
En el paso uno simplemente mostramos el botón “back”, esto es porque de inicio está oculto y lo que necesitamos es que se visualice cuando el usuario avanza a la segunda pantalla. En el paso dos solamente se verifica que no sea el último paso del wizard, la propiedad “this.index” es un contador que nos servirá para saber en cual paso esta el usuario, si no es el ultimo paso entonces se incrementa la propiedad “index” en uno. El paso dos es importantisimo, aquí tomamos el “CardLayout” que estamos usando para el wizard, el método “getLayout” regresa la instancia del layout que estamos usando. Una vez que tenemos el layout podemos asignarle una nueva carta usando el método “setActiveItem”. En el paso cuatro revisamos si al cambiar de carta se está desplegando la última, de ser así se ocultará el botón “next” y se mostrará el botón “finish”.

Retroceder en los pasos del wizard

Hasta este punto podemos avanzar en el wizard y llegar al final, ahora vamos a darle la opción al usuario de poder retroceder en los pasos del wizard, para eso creamos la función “back” de la siguiente manera.
back : function(){
	if(this.index>0){	//step 1
		this.index--;
		var cardlayout = this.form.getLayout();
		cardlayout.setActiveItem(this.index);
	}
	
//step 2
	if(this.index == 0){	//si está en la primera carta
		this.backBtn.hide();	
	}else{	//step 3
		this.finishBtn.hide();
		this.nextBtn.show();
	}
},
En el paso uno verificamos que el usuario no esté visualizando el paso número uno del wizard ya que si estamos al inicio no es posible seguir retrocediendo, si “index” es mayor a cero entonces si es posible retroceder y cambiamos la pantalla. En el paso dos revisamos que si al retroceder el usuario esta viendo el primer paso entonces ocultamos el botón “back”, ya que no es necesario seguir mostrándolo. El paso tres se ejecuta siempre y cuando no estemos en el primer paso, aquí ocultaremos el botón “finish” y mostraremos el botón “next” ya que si se ha presionado el botón “back” es seguro que ya no estamos en el ultimo paso.

Finalizando el wizard

Ya tenemos la funcionalidad básica, el usuario puede avanzar y retroceder entre los pasos que tiene el wizard, ahora tenemos que programar lo que necesitamos realizar cuando el usuario ha concluido con el wizard, esto es cuando da click sobre el botón “Finish”, para esto creamos el handler del botón de la siguiente manera:
finish	: function(){
	this.form.getForm().submit({
		url		: "createConnection.php",
		scope	        : this,
		success	: this.msg,
		failure	: this.msg
	});
},
Aquí puede ir el código que desees, para este ejemplo solamente se le ha hecho un “submit” al formulario principal enviando la información al archivo “createConnection.php” el cual debería poder gestionar la información recibida y procesarla correctamente, una vez que responde el servidor se ejecutará la función “msg” la cual será algo como lo siguiente:
msg	: function(){
	Ext.Msg.alert("Alert","Your connection has been created succesfully.");
	this.win.close();
}
Aquí también puedes poner lo que desees, en este caso solamente se despliega un mensaje y además se cierra la ventana del wizard automáticamente.

Conclusion

En este tutorial vimos algunos puntos importantes como la creación de un “CardLayout”, también se discutió sobre la manera de moverse sobre las cartas creadas y algo que quiero resaltar es la manera en como usamos un solo formulario para todos los campos que había en las cartas, esto nos permite recolecatar la información de una manera extremadamente sencilla. Si tienes alguna duda o sugerencia te recomiendo dejarnos un comentario o visitar nuestros foros, cada día va creciendo la comunidad y cuenta con usuarios dispuestos en ayudarte.

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

Este tutorial pertenece al curso Aprendiendo Ext JS 3, 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?

2Comentarios

Instructor del curso

Crysfel3

Autor: Crysfel Villa

Es ingeniero de software con más de 7 años de experiencia en desarrollo web.

Descarga Código Fuente Ver Demostración

Regístrate a este curso

Este tutorial pertenece al curso Aprendiendo Ext JS 3, 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.

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.