Introducción a Angularjs

A la hora de crear el frontend de una aplicación web, los pasos a seguir son los siguientes: En un primer momento, a partir de un diseño, se crea una plantilla mediante Html y Css, esto se llama maquetar. Pero lo único que obtenemos no es más que un sitio estático, con poco alcance, es entonces que recurrimos a Javascript, para hacer bailar a nuestro html. Javascript permite extender más allá la funcionalidad nuestros sitios en el lado del cliente. Con Javascript podemos manipular, crear y eliminar etiquetas; validar formularios; crear animaciones; etc. En pocas palabras Javascript convierte a html, algo estático en algo dinámico.

Angularjs es un framework creado por Google, basado en el MVC (Modelo Vista Controlador), algo con lo que se viene trabajando hace mucho tiempo en aplicaciones de backend, ahora implementado en el frontend. El modelo serán los datos que interactúan con el cliente, la vista será la presentación (Html) y el controlador la lógica (Javascript) De esta forma, podremos ordenar nuestro código.

Con esta publicación no pretendo iniciar un tutorial de Angularjs, como ya lo hice con otras tecnologías, sino que veremos una breve introducción para entender Angular y así profundizar en el mismo en un futuro, para aquellos que les interese.

Instalar Angularjs

En primer lugar vamos a entrar en la página, para incluir la librería:

https://angularjs.org/

En mi caso yo voy a copiarme la ruta absoluta, para mostrar los siguientes ejemplos.

Html dinámico

El Html es estático, lo sé, pero Angular pretende que esto cambie, mediante una serie de instrucciones y atributos que podremos usar. Para ello veremos un ejemplo similar al primero que se encuentra en la página:

Html:

<!doctype html>
<html ng-app>
   <head>
      <title> Ejemplo Angular </title>
      <script src="https://code.angularjs.org/1.2.10/angular.min.js"></script>
   </head>
   <body>
   <form>
      <label> Nombre </label>
      <input type="text" ng-model="nombre" />
      <span> {{nombre}} </span>
   </form>
   </body>
</html>

En primer lugar incluimos el atributo «ng-app», el cual nos permitirá que Angular pueda manipular nuestras etiquetas:

<html ng-app>

Luego creamos una etiqueta que contará con un modelo al que llamaremos «nombre»:

<input type="text" ng-model="nombre" />

El atributo «ng-model», al igual que «ng-app», es un atributo propio de Angular.

Finalmente utilizamos una variable con el mismo nombre del modelo, que definimos mediante a la doble apertura y doble cierra de llaves:

<span> {{nombre}} </span>

Esta variable «{{nombre}}», estará pendiente del valor del modelo con ese mismo nombre. Por ello en el momento que el valor de ese campo de ingreso se modifica, lo mismo pasará con esa variable, la cual nos mostrará dicho cambio en tiempo real:

También podemos aplicar funcionalidad dentro de las llaves, por ejemplo hacer operaciones matemáticas:

<!doctype html>
<html ng-app>
   <head>
      <title> Ejemplo Angular </title>
      <script src="https://code.angularjs.org/1.2.10/angular.min.js"></script>
      <script src="script.js"></script>
   </head>
   <body>
      <form>
         <label> Suma </label>
         <input type="number" ng-model="numero1" /> +
         <input type="number" ng-model="numero2" />
         <span> {{numero1 + numero2}} </span>
      </form>
   </body>
</html>

Controladores

Los controladores nos permitirán indicarle un determinado comportamiento a nuestros elementos. Para eso vamos a hacer otro ejemplo similar al de la página. Tendremos una lista de items que se podrán tildar o destildar, un botón para ingresar un nuevo item a la lista, y un enlace que al pulsarlo borrará aquellos que estén tildados.

El código html será el siguiente:

<!doctype html>
<html ng-app="miAplicacion">
   <head>
      <title> Ejemplo Angular </title>
      <script src="https://code.angularjs.org/1.2.10/angular.min.js"></script>
      <script src="script.js"></script>
   </head>
   <body>
      <div ng-controller="Controlador"> 
         <a href="#" ng-click="eliminar()"> Eliminar seleccionados </a>
         <ul>
            <li ng-repeat="item in lista"> 
               <input type="checkbox" ng-model="item.seleccionado" />
               <span> {{item.texto}} </span>
            </li>
         </ul>
         <form ng-submit="agregar()">
            <input type="text" ng-model="texto" />
            <input type="submit" value="Agregar" />
         </form>
      </div>
   </body>
</html>

Y a la misma altura crearemos un archivo javascript, con el nombre script.js:

var miAplicacion = angular.module('miAplicacion', []);
miAplicacion.controller('Controlador', ['$scope', function($scope) {
      $scope.lista = [
         {texto: 'GTA V', seleccionado: true},
         {texto: 'Call of duty', seleccionado: false}
      ];
      $scope.agregar = function() {
         $scope.lista.push({texto: $scope.texto, seleccionado: false});
         $scope.texto = '';
      };
      $scope.eliminar = function() {
         var lista = $scope.lista;
         $scope.lista = [];
         angular.forEach(lista, function(item) {
            if (!item.seleccionado)
               $scope.lista.push(item);
         });
      };
 }]);

En primer lugar hemos creado un módulo, al cual le asignamos posteriormente el controlador

var miAplicacion = angular.module('miAplicacion', []);

Si bien no necesitamos tener un módulo para crear un controlador, es una buena práctica hacerlo, para así ordenar nuestros controladores.

Luego para disponer de las funcionalidades de este módulo, hemos agregado el atributo «ng-app», a nuestra etiqueta html con el valor del módulo, y así disponer de éste en sus etiquetas hijas:

<html ng-app="miAplicacion">

Ahora, sí, vamos a analizar nuestro controlador, que valga la redundancia, se llama ‘Controlador’ (perdón por mi poca imaginación) Éste recibirá como parámetro el scope, que es un objeto que nos permitirá asignarle propiedades y métodos al controlador, y así disponer de los mismos en las etiquetas hijas a la cual asignamos el controlador:

<div ng-controller="Controlador">

Ahora bien, dentro de nuestro controlador, hemos asignado a nuestro scope la propiedad array, lista:

$scope.lista = [
   {texto: 'GTA V', seleccionado: true},
   {texto: 'Call of duty', seleccionado: false}
];

Esta contará con dos posiciones con defecto, con el nombre de un videojuego, y el valor true o false, dependiendo de si está seleccionado o no (esto último es para los checkbox)

Ahora para mostrarlos dentro del html, simplemente usaremos la propiedad «ng-repeat», que nos permitirá recorrer una lista:

<li ng-repeat="item in lista"> 
   <input type="checkbox" ng-model="item.seleccionado" />
   <span> {{item.texto}} </span>
</li>

Lo bueno de esto, es que gracias a la propiedad ng-model, el valor del checkbox, dependiendo de si el usuario lo ha tildado o no, estará conectado directamente con el array lista, por tanto, si cambia en uno, lo hará en tiempo real en el otro.

Luego tendremos un método para agregar un nuevo item a la lista:

$scope.agregar = function() {
   $scope.lista.push({texto: $scope.texto, seleccionado: false});
   $scope.texto = '';
};

Que será llamado desde nuestro formulario al pulsar en el botón, «input submit», gracias a la propiedad «ng-submit»:

<form ng-submit="agregar()">
   <input type="text" ng-model="texto" />
   <input type="submit" value="Agregar" />
</form>

Al dispararse el evento submit en el formulario, se llamará al método agregar(), el cual detectará que el modelo «texto» tiene un nuevo valor y lo guardará en la lista.

Y finalmente hacemos lo mismo con el método eliminar(), el cual borrará de la lista los items que estén tildados:

$scope.eliminar = function() {
   var lista = $scope.lista;
   $scope.lista = [];
   angular.forEach(lista, function(item) {
      if (!item.seleccionado)
         $scope.lista.push(item);
   });
};

Este evento se disparará gracias a la propiedad «ng-click», y el valor del método:

<a href="#" ng-click="eliminar()"> Eliminar seleccionados </a>

De este modo tenemos un perfecto ejemplo de lo que es capaz Angular, de cómo puede separar la lógica de la vista:

Directivas

Las directivas son, probablemente, el punto más interesante de Angular. Las directivas nos permitirán manipular el comportamiento de nuestros elementos html mediante la creación de atributos, clases, comentarios, e incluso la creación de nuevas etiquetas.

Supongamos que nosotros tenemos esto:

<!doctype html>
<html ng-app="miAplicacion">
   <head>
      <title> Ejemplo Angular </title>
      <meta charset="utf-8">
      <script src="https://code.angularjs.org/1.2.10/angular.min.js"></script>
      <script src="script.js"></script>
   </head>
   <body>
      <persona nombre="Fernando" apellido="Gaitán"></persona>
   </body>
</html>

Como se ve en el ejemplo tenemos una etiqueta con el nombre persona, que obviamente no pertenece a la familia de etiquetas de html, pero nosotros a través de una directiva la integraremos, para que el navegador pueda interpretarla.

A la misma altura creamos un archivo «script.js» con el siguiente código:

angular.module('miAplicacion', [])
   .directive('persona', function() {
      return {
         restrict: 'E', 
         scope: {},
         replace: true,
         template: '<h1> {{nombre_completo}} </h1>',
         link: function(scope, elemento, atributos){
            scope.nombre_completo = atributos.nombre + ' ' + atributos.apellido;
            elemento.bind('click', function(){
               alert('Hola, soy ' + scope.nombre_completo);
            });
         }
      };
   });

Vamos a analizar el código.

En primer lugar nuestra directiva tendrá un nombre ‘persona’.

Con respecto a la propiedad restrict, esto nos servirá para indicar si estamos creando un atributo, una clase, un comentario o un elemento. Como en nuestro caso es un elemento, el valor será ‘E’. Otros valores posibles son ‘A’, para atributo; ‘C’, para clase; y ‘M’ para comentario:

  • A: <div persona></div>
  • E: <persona></persona>
  • C: <div class=»persona»></div>
  • M: <!– directive: persona –>

También definiremos una propiedad scope igualada a un json vacío:

scope: {}

De esta manera nos aseguramos que cada vez que creemos una instancia de esta directiva tenga su propio scope, y no se pise con el scope de otro.

Con la propiedad template, definiremos el aspecto de nuestro elemento. En nuestro caso será simplemente un h1, con una variable «nombre_completo», que crearemos en el siguiente paso:

template: '<h1> {{nombre_completo}} </h1>'

Y finalmente mediante el método link(), crearemos toda la funcionalidad de nuestro elemento. Este método recibirá tres parámetros: el scope, el elemento en sí y sus atributos:

link: function(scope, elemento, atributos){
   scope.nombre_completo = atributos.nombre + ' ' + atributos.apellido;
   elemento.bind('click', function(){
      alert('Hola, soy ' + scope.nombre_completo);
   });
}

Asignamos al scope una propiedad «nombre_completo» (que es la que pasamos al template) con los valores de los atributos «nombre» y «apellido». Y también asignamos un evento click(), para que al pulsar sobre el evento ejecute un alert() que salude con el nombre completo. Notar que la sintaxis está basada en Jquery, lo cual facilita bastante las cosas a los desarrolladores que vengan de ese framework.

Sin embargo con esto último romperíamos un poco con la idea del MVC que propone Angular, ya que tanto las directivas como los controladores pertenecen a la lógica de nuestra aplicación, y nosotros estamos incluyendo una vista, osea código Html, la presentación dentro de la lógica.

Para el siguiente ejemplo vamos a incluir un nuevo elemento, el cual estará conformado por dos campos de ingreso, uno de entrada y otro de salida, y un botón que calcule la diferencia entre el primero y el segundo.

index.html:

<!doctype html>
<html ng-app="miAplicacion">
   <head>
      <title> Ejemplo Angular </title>
      <meta charset="utf-8">
      <script src="https://code.angularjs.org/1.2.10/angular.min.js"></script>
      <script src="script.js"></script>
   </head>
 <body>
   <form>
      <input type="text" name="contador[]" contador />
      <input type="text" name="contador[]" contador/>
      <input type="text" name="contador[]" contador/>
   </form>
 </body>
</html>

script.js:

angular.module('miAplicacion', [])
   .directive('contador', function() {
      return {
         restrict: 'A', 
         scope: {},
         replace: true,
         templateUrl: 'contador.html',
         link: function(scope, elemento, atributos){
            scope.name = atributos.name;
            elemento.removeAttr('name');
            scope.suma = 0;
            scope.resta = 0;
            scope.total = 0;
            scope.calcular = function(){
               scope.total = scope.suma - scope.resta;
            };
         }
      };
   });

contador.html:

<div>
   <label> Entrada </label>
   <input type="number" value="0" ng-model="suma" style="width: 50px;" />
   <label> Salida </label>
   <input type="number" value="0" ng-model="resta" style="width: 50px;" />
   <input type="button" value="Calcular" ng-click="calcular()" />
   <input type="text" name="{{name}}" value="0" ng-model="total" readonly="readonly" style="width: 50px;" />
</div>

Aquí entonces podemos ver cómo hemos incluido un «input text» al cual le agregamos un atributo contador:

<input type="text" name="contador[]" contador />
<input type="text" name="contador[]" contador/>
<input type="text" name="contador[]" contador/>

Este atributo es el que nos permitirá aplicarle la regla en nuestra directiva:

restrict: 'A',

Recordar que ‘A’ es para Atributos, mientras que en el ejemplo anterior usábamos ‘E’, para elementos.

Pero en este caso usáremos una plantilla externa, para así separar el código Html mediante la propiedad templateUrl:

templateUrl: 'contador.html',

Que incluirá el archivo con dicho nombre.

Para aquellos que les interese profundizar con Angularjs, pueden consultar la guía:

https://docs.angularjs.org/guide/

Saludos!


19 Respuestas a “Introducción a Angularjs”

  1. Eh, fernando realmente interesante, gracias por compartir. estare compartiendo con otras personas tu blog

      1. Excelente artículo, gracias por la colaboración por los que estamos iniciando. Saludos desde Colombia

  2. He estado siguiendo los ejemplos y hasta ahora me han parecido muy claros y presisos, de hecho, en pocos sitios me ha pasado que siguiendo las instrucciones todo funciona, sobre todo con nodejs.

    Muchas gracias por el esfuerzo, al menos a mi me ha ayudado mucho y me a parecido excelente!.

    Felicidades

  3. Hola ferchu, muy buena explicación, ahora una consulta, si quisiera mandar datos de checkbox seleccionados a otra vista como lo haría?

  4. Hola Fernando buen día, al principio del artículo leí que no planeas crear un tutoial, conoces alguno de preferencia en español? Que empiece desde cero

  5. Muy buen tutorial. Es realmente gratificante encontrarte con material tan fácil de entender, en español y con ejemplos reales. Gracias!!

  6. Saludos Tengo una pregunta para ver si podrias ayudarme. Estoy aprendiendo Angular y quiero hacer una tabla que tenga un arreglo de enlaces.
    en el .js. Tengo esto

    function EnlaceController($scope) {
    $scope.enlaces=[
    {enlace:»Ordenes Administrativas»},
    {enlace:»Avisos Publicos»},
    {enlace:»Resoluciones Especiales»},
    {enlace:»Borradores para Vistas Publicas»}
    ];
    }

    Como le incluyo en el scope el enlace a estos nombres?

    Si puedes ayudarme te agradezco

  7. Muy buen tutorial, de verdad muy interesante y realmente bien explicado.