Los controladores son clases que se encargan de gestionar el flujo de ejecución de la capa de presentación. En concreto se encarga de añadir y manipular la información que está el en $scope (view-model en la arquitectura MVVM o MVW) y añadir funciones de código JavaScript que luego será invocado desde los eventos del DOM.

 

Todo el código que se encargue de modificar el DOM no debería estar en esta capa. Esta capa debe contener simplemente la lógica de presentación de forma que sea el punto más importante sobre el que ejecutar las pruebas. Para pasar información del HTML a JavaScript o viceversa deberá añadirse al $scope como propiedades los valores que se precisen o como funciones el código que maneje los diferentes eventos a modo de comandos.

 

Los controladores deben ser muy sencillos ya que solo deben encargarse de la gestión de la lógica de presentación. Si fuese necesario añadir bastante código, hay que pensar en refactorizar y poner este código en factorías, servicios, filtros, decoradors, … que se verán más adelante en el tutorial. Además de todo esto también se pueden inyectar valores predefinidos (empiezan por $ como $scope, $http, $rootScope, $window, … )

 

Los controladores en todo momento se pueden anidar dentro del árbol de DOM de THML de forma que sus respectivos $scope también se embeberán. La idea con esto es que un $scope anidado dentro de otro extiende el padre con sus propias propiedades y funciones. (En el siguiente capítulo se explicará con extensión este punto importantísimo dentro de Angularjs)

 

Manejar el $scope desde el controlador

 

El $scope contiene la información necesaria que se desea mostrar en la página y el código para gestionar su flujo.

 

Para que un valor sea visible desde la capa de presentación solo es necesario añadir al $scope una propiedad con el valor que se desee pasar. Luego desde la capa de presentación ya enlazará esta propiedad al elemento correspondiente del DOM utilizando directivas o {{…}}. Si el enlace que se crea es de tipo twoway-binding (usando ng-model), cuando se modifique el valor en los controles del DOM se actualizará automáticamente el valor del $scope (para más información el siguiente post).

 

En el caso que se pretenda añadir un comportamiento se actuará de la misma forma, añadiendo en este caso una función al $scope. Luego se enlazará esta función a los eventos que se lancen desde el DOM (utilizando directivas como ng-click) de forma que cuando se invoquen los eventos se ejecutará el código que contenga la función añadida al $scope.

 

Esta forma de trabajar usando bindings es fundamental tenerla clara, así como la forma de enlazar propiedades, objetos y funciones desde el DOM para poder invocar y controlar el flujo de la capa de presentación. Este punto está explicado en el Capítulo 2 Arquitectura que es necesario entender y asimilar.

Asociar Controlador a un determinado html

La forma nativa de asociar un controlador al HTML es utilizar la directiva ng-controller:

angularjs controladores
Ejemplo 1: Introducción

 

En este ejemplo se puede ver como dentro del controller listController se inicializa la propiedad list que luego será recorrida en el ng-repeat para listar los elementos. Al mismo tiempo se añade la función add que luego será invocada en el ng-click del botón para añadir un elemento a la colección (el item que se inicializa en el ng-model=”item”).

 

Otra forma que es menos verbose y que parece más limpia es utilizando el “controller as xxx”.

angularjs controladores
Ejemplo 2: Controller as

Esta forma que elimina la palabra “scope” a cambio del this hace menos verbose el código y más legible, ya que el this de la función es directamente lo que hace bind contra el DOM.

 

El único inconveniente es cuando cambia el this al cambiar de ámbito. Por ejemplo en bucles, funciones, promises, … en estos casos hay que poner a la entrada del controlador el código var that = this; y a partir de ese punto referenciar a that en vez de this. Esto es algo que es usual con el uso de this en los objetos JavaScript.

 

Para más información ver la respuesta más votada en http://stackoverflow.com/questions/21287794/angularjs-controller-as-syntax-clarification.

 

Otra forma de asociar un controller al DOM es el uso de una directiva como vemos en el ejemplo y veremos más adelante en el post sobre directivas.

controladores angularjs ejemplo 3
Ejemplo 3: Directiva

 

 

Inyección de dependencias

Como es bien sabido, la forma de poder compartir información o funcionalidades entre diferentes dependencias es utilizar Value/Constant o Factory/Service. Con estos tipos de objetos de angularjs se pretende encapsular valores o funcionalidades que luego serán inyectadas a los controladores para ser usados.

 

Si por ejemplo tenemos un Service que se encarga de hacer un post a la lógica de negocio simplemente hay que poner como argumento en el controller el nombre del Service y este mágicamente aparecerá relleno.

 

Hay que tener en cuenta que los factories y services son siempre objetos singleton, con lo que si se inyectan en varios sitios el objeto que se inyecta es el mismo. No se va a inyectar un objeto nuevo cada vez.

 

Un ejemplo es el que se puede ver en el primer ejemplo de este post donde al controller se le inyecta el $scope.

 

angularjs tutorial 5 controladores
Ejemplo 1: Introducción

 

Esto aparentemente va fenomenal hasta que entra en juego un minificador. El problema de esta solución es que se está utilizando en nombre del parámetro como clave para buscar al objeto. De esta forma si el minificador cambia $scope por X para reducir el tamaño del código esto dejará de funcionar ya que buscará X entre los servicios, factorías, constantes, valores, palabras reservadas, … y no lo encontrará.

 

Para solucionar esto hay dos formas de hacerlo:

 

La primera opción es un poco más verbose y permite una codificación más fluent. Con esta opción se buscaría X en la lista de parámetros de la función y luego se buscaría en el array de strings por posición a qué texto corresponde con el que ya encontraríamos que objeto representa ese argumento.

 

tutorial angularjs controladores
Ejemplo 4: Minificación inline

 

La otra opción de hacerlo que parece menos verbose es utilizando $inject. Con esto el efecto conseguido es el mismo que con la minificación inline:

 

angularjs minificacion
Ejemplo 5: Minificación js

 

Un aspecto importante de ambos casos que es al hacer explícito en el array el nombre de los parámetros de la función permite cambiar el nombre del argumento. Esto es debido a que realmente el match se hace desde el array de nombres y luego se hace match con los parámetros por posición, por lo que el nombre ya no es la clave para buscar el objeto. Para mostrarlo, he llamado info al $scope para que se vea q se puede cambiar sin problemas en ambos casos en los ejemplos anteriores.

 

Para más información mirar la documentación oficial de Angularjs.

@_PedroHurtado y @XaviPaper

Vínculo hacia el capitulo anterior: (4) Modulo y hasta el siguiente: (6) Scope

Compartir
Ingeniero Informático por la Universidad Politécnica de Valencia, Xavier Jorge (@XaviPaper) trabaja como CTO de Ami2 y lleva más de 13 años vinculado a proyectos de I+D+i con diversas universidades, y desarrollando y arquitecturando soluciones con tecnologías .Net.

No hay comentarios

Dejar respuesta