Crearemos una aplicación sencilla con la intención de practicar con controller en AngularJS, inicializando datos en el Scope, creando manejadores de eventos, etc.
Vamos a hacer un ejercicio práctico de todo lo que venimos aprendiendo con AngularJS y donde afianzar particularmente lo aprendido sobre la creación de controladores .
El ejercicio es muy sencillo en realidad. Es un "acumulador" en el que tenemos un campo de texto para escribir una cantidad y un par de botones con operaciones de sumar y restar. Luego tenemos un contador que se va incrementando con esas operaciones de sumas y restas sobre un total. En si no sirve para mucho lo que vamos a construir, lo hacemos más bien con fines didácticos.
Puedes ver el ejercicio en marcha en Codepen antes de pasar a estudiar y explicar el código con el que se ha hecho.
Código HTML
Veamos primero la parte del HTML usada para resolver este ejercicio.
<div ng-app="acumuladorApp" ng-controller="acumuladorAppCtrl as vm">
<h1>Acumulador</h1>
<h2>Control de operación:</h2>
¿Cuánto? <input type="text" ng-model="vm.cuanto" size="4" />
<br />
<input type="button" value="+" ng-click="vm.sumar()"/>
<input type="button" value="-" ng-click="vm.restar()"/>
<h2>Totales:</h2>
En el acumulador llevamos <span>{{vm.total}}</span>
</div>
Voy describiendo los detalles más importantes que debes apreciar.
- Al hacer el bootstrap (arranque) de la aplicación (directiva ngApp) se indica el nombre del módulo: "acumuladorApp".
- Se indica el nombre del controlador con la directiva ngController y el valor "acumuladorAppCtrl".
- Con la sintaxis de "acumuladorAppCtrl as vm" indicamos que el scope dentro del espacio de etiquetas marcado para este controlador, se conocerá por "vm". Podríamos llamar como deseásemos al scope, en lugar "vm", en definitiva es como una variable donde tendremos propiedades y métodos. En otras palabras, se ha creado un namespace (espacio de nombres) para los datos que nos vienen del modelo (scope) gracias al controlador "acumuladorAppCtrl".
- Puedes llamar de cualquier manera también tanto a módulo como a controlador, pero se usan esos por convención.
- El campo INPUT de texto tiene una directiva ngModel para decirle a AngularJS que ese es un dato del modelo. Fítate que el nombre del dato en el modelo se accede a través del espacio de nombres definido en el controlador: "vm.cuanto".
- Luego encuentras dos INPUT tipo button que me sirven para realizar la acción de acumular, positiva o negativamente. Ambos tienen una directiva ngClick que nos sirve para expresar lo que debe ocurrir con un clic. Lo interesante aquí es que llamamos a dos funciones que están definidas en el scope, mediante el espacio de nombres "vm", nuestro modelo. El código de esos métodos (funciones que hacen en este caso de manejadores de eventos) ha sido definido en el controlador, lo veremos más adelante.
- Por último encontramos un {{vm.total}} que es un dato que estará en el scope y en el que llevamos la cuenta de todo lo que se ha sumado o restado con el acumulador.
Código Javascript
Ahora pasemos a la parte donde codificamos nuestro Javascript para darle vida a este ejercicio.
angular
.module('acumuladorApp', [])
.controller("acumuladorAppCtrl", controladorPrincipal);
function controladorPrincipal(){
//esta función es mi controlador
var scope = this;
scope.total = 0;
scope.cuanto = 0;
scope.sumar = function(){
scope.total += parseInt(scope.cuanto);
}
scope.restar = function(){
scope.total -= parseInt(scope.cuanto);
}
};
Vamos describiendo las principales partes del código.
- Con "angular" en la primera línea accedo a la variable que me crea angular, disponible para acceder a las funcionalidades del framework.
- En la segunda línea creamos el módulo, indicando el nombre (que es igual a lo que se puso como valor en la directiva ngApp del HTML) y el array de las dependencias, de momento vacío.
- En la tercera línea, con un encadenamiento (chaining) definimos el controlador. Indicamos como primer parámetro el nombre del controlador, definido en la directiva ngController del HTML, y como segundo parámetro colocamos la función que se encargará de construir el controlador. Indicamos el nombre de la función simplemente, sin los paréntesis, pues no es una llamada a la función sino simplemente su nombre.
- Luego se define la función del controlador. Esa función es capaz de escribir datos en el scope, así como métodos.
- En la función accedemos al scope por medio de "this". Fíjate que en la primera línea de la función tienes var scope = this; esto es simplemente opcional y se puede hacer para mantener la terminología de AngularJS de llamar scope a lo que vas generando en el controlador, pero podría perfectamente referirme a él todo el tiempo con "this".
- En el scope inicializo dos valores, total y cuanto, mediante scope.total=0 y scope.cuanto=0.
- Luego genero dos métodos que usaremos para los manejadores de eventos de los botones de sumar y restar. Esas funciones tienen el scope disponible también y en su código se accede y modifica a los datos del scope.
Con eso tenemos el ejercicio completo, todo lo demás para que esto funcione es tarea de AngularJS. De manera declarativa en el HTML hemos dicho qué son las cosas con las que se va a trabajar en la aplicación y luego hemos terminado de definir e inicializar los datos en el controlador, así como escribir en código las funcionalidades necesarias para que el ejercicio tome vida.
Variante de este mismo ejercicio pero sin "controller as"
En la resolución, que hemos comentado antes, a este ejercicio hemos usado una alternativa de la directiva de ngController en la que se le asigna un espacio de nombres al scope "acumuladorAppCtrl as vm". Esto se conoce habitualmente como "controller as" y ya comentamos en el artículo anterior dedicado a los controladores que es algo relativamente nuevo y que muchas veces la codificación que encontrarás en otros textos es un poco diferente.
Solo a modo de guía para quien está acostumbrado a trabajar de otra manera, y para que entiendas otros códigos antiguos que podrás encontrar en otras guías de Angular, pongo aquí el código de este mismo ejercicio pero sin el "controller as".
El código HTML
<div ng-app="acumuladorApp" ng-controller="acumuladorAppCtrl">
<h1>Acumulador</h1>
<h2>Control de operación:</h2>
¿Cuánto? <input type="text" ng-model="cuanto" size="4" />
<br />
<input type="button" value="+" ng-click="sumar()"/>
<input type="button" value="-" ng-click="restar()"/>
<h2>Totales:</h2>
En el acumulador llevamos <span>{{total}}</span>
</div>
El código Javascript
var acumuladorApp = angular.module('acumuladorApp', []);
acumuladorApp.controller("acumuladorAppCtrl", ["$scope", function($scope){
//esta función es mi controlador
//var $scope = this;
$scope.total = 0;
$scope.cuanto = 0;
$scope.sumar = function(){
$scope.total += parseInt($scope.cuanto);
}
$scope.restar = function(){
$scope.total -= parseInt($scope.cuanto);
}
}]);
No comento el código más, pues es muy parecido al anterior, simplemente se deja de usar el espacio de nombres y al definir la función del controlador se inyecta el $scope de otra manera. Te dejo a ti la tarea de encontrar todas las diferencias.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...