Ext.app.Controller

En Ext JS 3, regularmente agregábamos la lógica de nuestra aplicación a las mismas vistas en sí, utilizando botones controladores, esperando eventos de los componentes, sobrescribiendo métodos en las subclases vistas cuando se heredaban. Sin embargo, de manera similar que el estilo se separa en hojas de cascada del HTML, es preferible separar la lógica de la aplicación de la definición de las vistas. En ExtJS 4, se proporcionan controladores como parte de la estructura de las aplicaciones. Ellos son los responsables de esperar los eventos por las vistas y otros controladores, y aplicar la lógica de las aplicaciones para responder a esos eventos de interacción con el usuario. Hay muchos beneficios que esperar de este diseño.

Uno de los primeros beneficios es que la lógica de la aplicación es independiente de las instancias de los Componentes Vistas, lo que significa que se pueden instanciar y destruir las Vistas a necesidad, mientras que esa lógica continua procesando acciones, como sincronizando los datos por ejemplo. Adicionalmente, en ExtJS 3, las aplicaciones acumulaban vistas en cada capa de lógica. Separando esa lógica en los controladores, se centraliza, permitiendo que sea mas fácil de mantener y realizar cambios posteriores a la aplicación. Finalmente, la clase base Controller proporciona mucha funcionalidad preestablecida, haciendo también fácil implementar la lógica de tus aplicaciones.

Los Controladores son el enlace que une a toda la aplicación completa. Todo lo que en resumen hacen es escuchar los eventos (usualmente de las vistas) y realizan alguna acción. Aquí un ejemplo básico de cómo crear un Controlador para manipular usuarios:


<pre name="code" class="javascript">
Ext.define('MiApp.controller.Usuarios', {
   extend: 'Ext.app.Controller',
   init: function() {
      console.log('Usuario inicializado! Esto ocurre
      antes de que el método launch de la
      Aplicación sea ejecutado');
   }
});
</pre>


El método init de los controladores es un método especial que es llamado cuando tu aplicación es lanzada, antes de que el método launch de la Aplicación sea ejecutada, de esta manera te da la oportunidad de correr el código necesario para configurar las vistas antes de que sean creadas.

La función init es el lugar adecuado para estructurar como el controlador interactúa con la vista, usualmente las configuraciones se realizan en la función control definida en todos los controladores. El método control hace fácil escuchar los eventos en las clases vista y realizar algunas acciones con otras funciones controladoras.

En aplicaciones grandes, es muy probable que quieras agregar más Controladores en tiempo de ejecución. Es posible hacer esto utilizando el método getController, como el siguiente ejemplo


<pre name="code" class="javascript">
algunaAccion: function() {
var controller = this.getController('otroControlador');

// Recuerda llamar al método init MANUALMENTE
controller.init();
}
</pre>


Cuando se agregan Controladores adicionales en tiempo de ejecución, es importante recordar ejecutar su método init manualmente.

Veamos un ejemplo de cómo actualizar los datos de un usuario configurando el Controlador de usuario para avisarnos cuando se despliega su panel en pantalla:

<pre name="code" class="javascript">
Ext.define('MiApp.controller.Usuario', {
extend: 'Ext.app.Controller',

init: function() {
console.log('Usuario inicializado! Esto
pasa antes de que la aplicación sea lanzada');
this.control({
'viewport > panel': {
render: this.onPanelDesplegado
}
});

this.application.on({
iniciaaplicacion: this.onIniciaAplicacion,
scope: this
});
},

onPanelDesplegado: function() {
console.log('El panel ha sido desplegado');

this.application.fireEvent('iniciaaplicacion',
"Mensaje de bienvenida");
}
});
</pre>


Este controlador debe estar definido en la ruta MiApp/controller/Usuario.js

Actualizamos la función init para utilizar this.control para configurar los listeners de las vistas en nuestra aplicación. Esta función control utiliza el nuevo motor de coincidencia ComponentQuery para obtener referencia rápidamente de los componentes en la página. En pocas palabras, permite definir un selector como en CSS para encontrar todos los componentes que coincidan con la regla en la página.

En nuestro ejemplo escribimos ‘viewport > panel’, que se traduce como “encuéntrame todos los Paneles que sean hijos directos del Viewport”. Inmediatamente proporcionamos un objeto que mapea el nombre del evento con la función controladora (solo render en este caso). El resultado inmediato es que cualquier componente que concuerde con el selector definido disparara el evento 'render', y nuestro método onPanelDesplegado será llamado.

Adicionalmente de esperar el evento render de la Vista Panel, también proporcionamos un listener a nuestra aplicación. Hacemos esto mediante el metodo on de la instancia de la aplicación. Todos los controladores tienen acceso a la instancia de la aplicación utilizando la referencia this.application.

Los eventos de la aplicación son extremadamente útiles para eventos que lancen nuestros Controladores. En lugar de esperar el mismo evento de la Vista en cada uno de los Controladores, solo un Controlador escucha el evento y dispara un evento Completo a lo largo de toda la aplicación que los otros Controladores puedan escuchar. Esto también permite a los Controladores comunicarse entre ellos sin la necesidad de conocerse o tener dependencia entre ellos.

En nuestro ejemplo, podemos definir el evento iniciaaplicacion:

<pre name="code" class="javascript">
...
onPanelDesplegado: function() {
console.log('El panel ha sido desplegado');

this.application.fireEvent('iniciaaplicacion',
"Mensaje de bienvenida");
}
...
</pre>


Usando referencias

Una de las partes mas útiles de los Controladores es el nuevo motor de referencias. Este sistema utiliza las capacidades de Ext.ComponentQuery para obtener las referencias a las Vistas del Controlador. Un ejemplo de ello sería:

<pre name="code" class="javascript">
Ext.define('MiApp.controller.Usuario', {
extend: 'Ext.app.Controller',

refs: [
{
ref: 'lista',
selector: 'grid'//por el xtype
}
],

init: function() {
this.control({
'button': {
click: this.refreshGrid
}
});
},

refreshGrid: function() {
this.getLista().store.load();
}
});
</pre>


En Ext JS 3, una manera muy común de obtener la referencia de la instancia de un componente existente en la página era utilizando el método Ext.getCmp. A pesar de que este método continúe funcionando, no es la manera recomendada en Ext JS 4. Utilizar Ext.getCmp requiere que a cada componente se le asigne un único ID para obtener posteriormente la referencia. En la nueva arquitectura MVC de ExtJS4, podemos poner la referencia de la instancia de la Vista (un Componente) dentro del Controlador por medio del motor ComponentQuery.

En el ejemplo anterior se asume la existencia de un Grid en la página, que contiene un único botón para refrescar el Grid cuando se presiona. En nuestro arreglo de referencias, configuramos una referencia hacia nuestro Grid. Hay dos partes aquí, el 'selector' que es un selector de ComponentQuery para encontrar cualquier grid en la página y asigne la referencia a la variable 'lista' y la función getLista utilizada en el método refreshGrid. Esta última, generada automáticamente por el Controlador basado en el nombre de la referencia, que fue capitalizado y con el prefijo 'get' para ejecutar getLista. Es posible crear cualquier número de referencias hacia los componentes de esta manera.

El procedimiento de como esto funciona es que cuando se ejecuta getLista en tu código, el selector de ComponentQuery se compara para coincidir con algún componente ( ('grid' en este caso) y que sea retornado en la función.


Es importante recordar que los métodos getters serán creados independientemente de que la Vista exista o no en la página.


Cuando un selector no concuerda con ninguna Vista en la Aplicación, la función getter retornará null. Esto significa que si tienes instrucciones que dependen de que la Vista exista pero hay la posibilidad de que no esté instanciada, es necesario agregar alguna validación que garantice que el método getter retorne el componente esperado. Adicionalmente, si hay muchos componentes que coincidan con el selector, sólo el primero será regresado.


Es buena práctica de programación hacer los selectores específicos a una única Vista que se desee obtener.

Finalmente, cuando se destruye el componente de la referencia, llamar al método getter con el que se recuperaba, este retornara null nuevamente hasta que otro componente concuerde con el selector de la referencia.



Generando los métodos getters

Las referencias no son los únicos procedimientos para generar los métodos getters. Los controladores usualmente tienen que lidiar con Modelos y Stores, y el Framework ofrece algunas maneras fáciles de acceder a ellos. Veamos un ejemplo:


<pre name="code" class="javascript">
Ext.define('MiApp.controller.Usuario', {
extend: 'Ext.app.Controller',

models: ['Usuario'],
stores: ['Clientes', 'Administradores'],

init: function() {
var Usuario = this.getUsuarioModel(),
clientes = this.getClientesStore();

var joshua = new Usuario({nombre: 'Joshua'});
clientes.add(joshua);
}
});
</pre>


Especificando Modelos y Stores de los cuales el Controlador tiene que administrar, las clases se descargan automáticamente de sus respectivas rutas (MiApp/model/Usuario.js, MiApp/store/Clientes.js y MiApp/store/Administradores.js en este caso) y crean funciones getters para todos ellos. El ejemplo de arriba, creará una nueva instancia de Usuario (new Usuario) y se lo agrega al Store de Clientes.



Para mayor información de Aplicaciones en Ext JS 4, por favor revise la guía de Arquitectura de aplicación.


Opciones de configuración


• id : String
• models : String[]
• stores : String[]
• views : String[]



Métodos

• control( String/Object selectors, Object listeners )
• getController( String name ) : Ext.app.Controller
• getModel( String name ) : Ext.data.Model
• getStore( String name ) : Ext.data.Store
• getView( String name ) : Ext.Base
• init( Ext.app.Application application )
• onLaunch( Ext.app.Application application )



Porqué es importante aprender a programar? ...
El éxito de las estimaciones de recursos en el Software ...
La programación dirigida por eventos también es un paradigma de programación
Consideraciones a tomar para llamarlo el mejor

Danos tus comentarios

Escribe un comentario en el campo de abajo...