Guía de inicio en AngularJS. {+Demo}


En el artículo anterior hice algunas comparaciones sobre AngularJS y jQuery y de alguna forma te mostré los elementos para convencerte a utilizar el framework. En esta ocasión verás de forma práctica el ejemplo que te mostré sobre cargar ítems de forma remota y mostrarlos en la página sin recargar la misma.

La realización del ejemplo a su vez te servirá de guía para conocer los elementos principales del framework, por lo que si te parece un poco extenso, es porque te explico en detalle la existencia de cada componente en el demo que crearé.

Este consiste en una lista ordenada y un botón, donde al darle clic se cargarán en la lista de forma dinámica algunos artículos. Estos artículos pueden estar alojados en una base de datos, un servicio web, o simplemente en un fichero json. No obstante, para no complejizar el demo crearé los artículos en un arreglo y estableceré una función de tiempo para simular que se hizo una petición AJAX a un servidor remoto.

Manos a la obra

El código HTML que representan la lista y el botón es el siguiente:

<body ng-app="articulosApp"> 
  <ul id="lista"> 
    <!-- artículos aquí -->
  </ul>     

  <button ng-click="cargar()">
    Cargar artículos
  </button> 
</body>

Con respecto al ejemplo del artículo anterior hay dos cosas nuevas aquí. La primera es el valor que se le asigna a la directiva ng-app. Este valor se utiliza para identificar la aplicación y será utilizado desde Javascript. La segunda es la directiva ng-click que registra un evento clic en el botón y especifica que se ejecute la función cargar.

Esta función se debe implementar dentro de un controlador, que es el que se encargará de administrar el código anterior. Pero antes, este código anterior debe conocer cuál es tal controlador.

Para ello añade otra directiva al elemento body de la siguiente forma:

<body ng-app="articulosApp" ng-controller="MisArticulosCtrl">

Dicho esto puedes proceder a implementar una función que tenga el mismo nombre del valor que le asignaste a la directiva ng-controller. Nota que este valor no necesariamente tiene que terminar en Ctrl, pero es una convención que se usa mucho para identificar a una función controladora dentro del código Javascript.

Nota además que la declaración de esta directiva no tiene que estar junto con la directiva ng-app, puede estar en otra etiqueta, como por ejemplo un div que encierre a la lista y al botón.

Creando un módulo para la aplicación

Angular trabaja con el concepto de módulos. La aplicación tiene un módulo principal que toma el mismo nombre del valor de la etiqueta ng-app, el cual puede depender de otros módulos.

El código Javascript inicial es el siguiente:

<script type="text/javascript">
  var app = angular.module('articulosApp', []);
<script>

El segundo parámetro de la función module es un arreglo, que en este caso está vacío porque la aplicación no depende de ningún otro módulo.

Lo siguiente que haremos es crear la función controladora que contendrá la lógica de la aplicación.

app.controller('MisArticulosCtrl', function( $scope ){
  // Lógica de la app aquí
});

A partir del objeto app puedes crear tantos controladores como desees. En la función callback del método app.controller “implementas” todo lo que “definiste” en la vista. Esto significa que aquí es donde implementas la función cargar() que a su vez obtiene los elementos del servidor remoto mediante una petición AJAX.

 El objeto $scope es tu herramienta principal

Lo primero que te debes estar preguntando al ver el código anterior es: ¿Cómo llegó el objeto $scope a mi controlador? ¿Quién lo inicializó? ¿Qué es?

El scope (palabra en inglés que significa ámbito) es el objeto que une la vista con el controlador. Cada uno de los controladores tiene un scope diferente que conoce solo los elementos definidos en la parte de la vista que el controlador maneja.

Este objeto es inicializado automáticamente por Angular cuando se crea un controlador, y se “inyecta” en este quedando listo para ser utilizado. Esto es posible gracias al patrón llamado “Inyección de dependencias”.

Esto significa que no tienes que preocuparte por crear objetos en tu aplicación, con “inyectarlos” donde los necesitas basta. Por ejemplo, para crear una petición AJAX se utiliza el objeto $http de angular. Este objeto cuando necesites utilizarlo en algún controlador no lo creas, simplemente lo pasas por parámetro y lo utilizas.

¿Seguimos con el demo?

Por supuesto. Conociendo lo que es el $scope no te debe extrañar que la función cargar() debe formar parte de este objeto, porque en caso contrario la vista no sabría que existe.

Dicho esto se declara de la siguiente forma:

$scope.cargar = function(){
  console.log('Has dado clic en el botón');
}

Al dar clic en el botón se mostrará en la consola de tu navegador el mensaje, por tanto puedes proceder a obtener los artículos y mostrarlos en el documento HTML. Como te comenté antes, en vez de realizar una petición AJAX crearé la lista de artículos de forma estática en un arreglo y la mostraré en la vista. Esto se logra asignándole el arreglo creado al objeto $scope:

  var  arts = ['articulo1', 'articulo2', 'articuloN']; 
  $scope.articulos = arts;  

Al realizar esta acción la vista conoce que existe un listado de elementos dentro de la variable artículos, por tanto podemos proceder a terminar el ul que creamos al inicio.

<ul id="lista"> 
  <li ng-repeat="art in articulos">
    {{ art }}
  </li>  
</ul>

Qué simple. La directiva ng-repeat se encarga de repetir el elemento li tantas veces existan elementos dentro del arreglo artículos y, en cada iteración, le asigna cada elemento a la variable local art, la cual es mostrada como contenido del li encerrándola entre llaves dobles.

Las llaves dobles ({{ expresión }}) le indican a angular que debe “imprimir” la expresión contenida en ellas. Se admite a parte del contenido de variables, expresiones matemáticas y condicionales, ejemplo: {{ existe == true ? 'Sí, existe' : 'Nope, no existe' }}.

Con esto terminamos el demo. Al darle clic al botón aparecerán de forma instantánea todos los elementos de la lista. Nota que inicialmente, cuando se carga la página, la variable artículos en la vista ni siquiera existe, pero Angular es lo suficientemente inteligente como para no renderizar nada y, en el momento en que existan artículos, mostrarlos.

El siguiente Codepen muestra todo el código junto con el resultado en vivo!!!



  • {{ar}}

See the Pen Demo angularjs. Cargar articulos by Dimitri Lopez (@mycyberacademy) on CodePen.

¿Qué hacer si el contenido demora en cargar?

En las aplicaciones reales, lo que va en la función cargar() es una petición AJAX para obtener los datos de un servidor. Esto muchas veces conlleva a un pequeño lapso de tiempo antes de que se muestren los datos.

Lo que comúnmente se realiza es poner un indicador para indicarte que se está realizando la acción, y al finalizar, este se retira de la página.

Cuando se dé clic en el botón mostraré el mensaje “Cargando…” y lo eliminaré cuando se carguen los datos. Como estos datos se visualizan de forma instantánea crearé una función de tiempo que simule una petición al servidor.

$scope.cargar = function(){
  $scope.cargando = true;

  setTimeout(function(){
    
    var  arts = ['articulo1', 'articulo2', 'articuloN']; 
    $scope.articulos = arts;  
    $scope.cargando = false;
  
  }, 2000);
}

Lo primero que hago es crear una variable con valor true en el $scope, luego creo el timeout que demorará en ejecutarse 2 segundos. Luego de estos 2 segundos se cargan los artículos y la variable cargando se establece a false. Esta variable es la que permitirá visualizar y esconder el mensaje “Cargando…” en la vista. Si escribes lo siguiente justo después del elemento body:

<span ng-show="cargando"> Cargando… </span>

Logras que ese elemento se muestre si y solo si la variable cargando es verdadera. Con esto terminé el demo, pero espera, ¡No funciona!

Usa $timeout() en lugar de setTimeout()

Cuando estás aprendiendo Angular y algo no te funciona o te es muy tedioso lograr algo, pregúntate primero si existe algún objeto o método en el framework que te haga la vida más fácil.

En el ejemplo anterior, la vista no se actualizará automáticamente a los 2 segundos. El problema de por qué esto sucede lo explican al detalle en este artículo, pero como lo explicado en esa entrada es un poco más avanzado, puedes conformarte con saber que el framework tiene una función que la reemplaza: $timeout().

Esta variable, al igual que el $scope, la pides en los parámetros del controlador y la usas. Si reemplazas en el código anterior la palabra setTimeout por $timeout todo funcionará como se espera, verifícalo en el siguiente codepen:

Cargando…



  • {{ar}}

See the Pen oggrPZ by Dimitri Lopez (@mycyberacademy) on CodePen.

Conclusiones

Angular es increíble. Como es una tecnología del lado del cliente, puedes utilizar del lado del servidor lo que desees, o sea, no interesa si usas Symfony, Phalcon, Laravel, CodeIgniter o cualquier otro framework para programar, a Angular no le importa, con el servicio $http que trae puedes realizar cualquier tipo de peticiones. Incluso, si tu servidor está configurado como una API Rest es mejor, pues el módulo $resource encapsula toda la lógica necesaria para lidiar con este tipo de configuraciones.

En el próximo artículo estaré mostrándote las opciones disponibles para realizar peticiones con AJAX, sin más, hasta la próxima.