Angularjs

2.2. Tour rápido por las características de AngularJS

En este capítulo vamos a ver una visión general de todo el framework AngularJS de una forma muy rápida. De esta manera podremos tener un ámbiente del curso y después entraremos en detalle.

Las características de AngularJS se pueden resumir:

  • Directivas, Filtros y Vinculación de datos (directives, filters, data-binding)
  • Vistas, Controladores y el ámbito (views, controllers, scope)
  • Módulos, Rutas y Factorias (modules, routes, factories)

Directives, Filters y Data-Binding

¿Qué son las Directivas (directives)?

Las directivas son etiquetas en un elemento del DOM (un atributo, un nombre de elemento, comentario o clase CSS) que indican al compilador de HTML de AngularJS ($compile) cuál debe ser su compartamiento.

Cuando AngularJS empieza la aplicación parsea y proceso las nuevas etiquetas de la template "compilando". Después acaba renderizando el DOM llamando a la vista (view).

Aplica a las directivas

Las directivas enseñan trucos al HTML

En el ejemplo de Hola mundo visto anteriormente podemos apreciar la utilización de algunas de nuestras primeras directivas.

ng-app es la directiva principal de AngularJS. Determina el elemento root (raíz) de la aplicación. Típicamente se suele poner en <html> o <body>

Directiva ng-app

ng-model es la directiva que enlaza (binds) un campo de formulario input, select, textarea con el ámbito (scope) de la vista.

Directiva ng-model

La potencia de AngularJS es que nos permitirá crear nuestras propias directivas.

Data-binding

AngularJS enlaza los datos de forma automática entre el modelo y los componentes de la vista/interfaz.

Cuando el modelo cambia en la vista se ve reflejado el cambio y viceversa: two-way data binding

Data-binding

Data-binding

Filters

Un filtro formatea el valor de una expresión en una visualización concreta o filtra incluso resultados a partir de esa expresión.

Los filtros formatea una expresión por ejemplo en mayúsculas, minúsculas, formato de moneda, formato de fecha...

Estos filtros pueden ser utilizados en AngularJS tanto en las vistas (templates view) , controladores (controllers) o servicios (services)


ng-repeat

Veámos un ejemplo ejemplo 2.2

Creamos una lista de libros mediante un array con la directiva ng-init que se ejecuta al crear el elemento HTML: ng-init="libros=['El Juego de Ender','Juego de Tronos','I robot']"

Después utilizamos la directiva ng-repeat para iterar una colección de datos mediante un loop y tener así una duplicación de parte de la interfaz gráfica pero con diferentes datos. En definitiva una especie for each.

<html ng-app>
    <body>
        <div ng-init="libros=['El Juego de Ender','Juego de Tronos','I robot']">
             <h1>Listado de libros</h1>

            <ul>
                   <li ng-repeat="libro in libros">{{ libro }}</li>
            </ul>
        </div>
        <script src="angular.min.js"></script>
    </body>
</html>

Pantalla ng-repeat

Formatear una cadena

Una vez tenemos la lista de libros queremos poder poner todos los títulos en mayúsculas. Es tan sencillo como aplicar el filtro por defecto: {{ libro | uppercase }} ejemplo 2.3

Pantalla ng-repeat uppercase

Filter

También mediante los filtros podemos filtrar el listado de libros de una forma rápida y sencilla simplemente filtrando la colección de datos del ng-repeat mediante ng-repeat="libro in libros | filter:nombre" donde nombre sería una variable definida por un modelo (ng-model) en un input.

Así que cuando el usuario rellene ese input nombre automáticamente se filtrará la colección de datos dejando en pantalla sólo los datos que concuerden con ese filtro.

<html ng-app>
    <body>
        <div ng-init="libros=['El Juego de Ender','Juego de Tronos','I robot']">
             <h1>Listado de libros</h1>
             Nombre: <input type="text" ng-model="nombre" />

            <ul>60
                   <li ng-repeat="libro in libros | filter:nombre">{{ libro | uppercase }}</li>
            </ul>
        </div>
        <script src="angular.min.js"></script>
    </body>
</html>

ejemplo 2.4

Pantalla ng-repeat filter por nombre

OrderBy

Otro filtro interesante aplicable es poder ordenar de forma automática mediante orderBy.

Cambiamos la colección de datos por una estructura clave/valor, por ejemplo, cada libro con su nombre y autor: ng-init="libros = [ {titulo:'El Juego de Ender', autor:'Orson Scott Card'}, {titulo:'Juego de Tronos', autor:'George R.R. Martin'}, {titulo:'I robot', autor:'Isaac Asimov'} ]

Podríamos después poder ordenar por cada uno de sus campos, en este caso por el nombre del autor ng-repeat="libro in libros | filter:nombre | orderBy:'autor'"

<html ng-app>
    <body>
        <div ng-init="libros = 
        [
            {titulo:'El Juego de Ender', autor:'Orson Scott Card'},
            {titulo:'Juego de Tronos', autor:'George R.R. Martin'},
            {titulo:'I robot', autor:'Isaac Asimov'}
        ]">

             <h1>Listado de libros</h1>
             Nombre: <input type="text" ng-model="nombre" />

            <ul>
                   <li ng-repeat="libro in libros | filter:nombre | orderBy:'autor'">{{ libro.titulo | uppercase }} - {{ libro.autor}}</li>
            </ul>
        </div>
        <script src="angular.min.js"></script>
    </body>
</html>

ejemplo 2.5

Pantalla ng-repeat orderby autor

View, Controllers and Scope

View

La vista (view) es la interfaz gráfica o HTML parciales que se renderizan en el navegador web para mostrar nuestra aplicación.

Controller

El Controlador (controller) responde a eventos (usualmente acciones del usuario) e invoca peticiones al 'modelo' cuando se hace alguna solicitud sobre la información.

Cuando un controllador en AngularJS se añade al DOM mediante la directiva ng-controller Angular instancia un objeto new Controller usando el constructor donde se le puede pasar por parámetro el $scope (ámbito).

view-scope-controller

$scope

El $scope es un objeto que se refiere al ámbito/contexto de ejecución de las variables. El $scope permite conectar la vista con el controlador y tener las variables bindadas


Reestructuramos ahora el mismo ejemplo del listado de libros añadiendo el concepto del Controllador. Para ello y a partir de la versión AngularJS 1.3 se requiere crear un módulo de la aplicación con lo que se requiere identificar a la aplicación app="miApp"

Por tanto definimos el controlador en un contenedor <div> y le damos un nombre <div ng-controller="miControlador">

Una vez identificada la app y añadido el controllador los definimos en javascript mediante la definición de un módulo y la creación del controlador. En el constructor del controlador crearemos el listado de libros.

 <script>
        var miApp = angular.module('miApp',[]);

        function miControlador($scope) {
            $scope.libros = 
            [
                {titulo:'El Juego de Ender', autor:'Orson Scott Card'},
                {titulo:'Juego de Tronos', autor:'George R.R. Martin'},
                {titulo:'I robot', autor:'Isaac Asimov'}
            ];
        }

        miApp.controller('miControlador', miControlador);
        </script>

Donde vemos que la definición de la aplicación como miApp sin dependencias [] y la definición del controlador miControlador pasándole por parámetro el $scope, es decir, el ámbito de variables de la vista.

miApp

Por eso al definir $scope.libros en el constructor del controlador puede ser utilizado luego en la vista como libros directamente ng-repeat="libro in libros

$scope.libros - libros

En nuestro caso utilizamos el mismo nombre del objeto de javascript con el nombre del controlador pero esto no es estrictamente necesario que sea así.

miCOntrolador

Por tanto el código final quedará de la siguiente forma:

<html ng-app="miApp">
    <body>
        <div ng-controller="miControlador">

             <h1>Listado de libros</h1>
             Nombre: <input type="text" ng-model="nombre" />

            <ul>
                   <li ng-repeat="libro in libros | filter:nombre | orderBy:'autor'">{{ libro.titulo | uppercase }} - {{ libro.autor}}</li>
            </ul>
        </div>

        <script src="angular.min.js"></script>
        <script>
        var miApp = angular.module('miApp',[]);

        function miControlador($scope) {
            $scope.libros = 
            [
                {titulo:'El Juego de Ender', autor:'Orson Scott Card'},
                {titulo:'Juego de Tronos', autor:'George R.R. Martin'},
                {titulo:'I robot', autor:'Isaac Asimov'}
            ];
        }

        miApp.controller('miControlador', miControlador);
        </script>
    </body>
</html>

Se puede simplificar un poco el código y definir directamente el controlador cuando lo añades a la app.

<script>
        var miApp = angular.module('miApp',[]);

        miApp.controller('miControlador', function($scope) {
            $scope.libros = 
            [
                {titulo:'El Juego de Ender', autor:'Orson Scott Card'},
                {titulo:'Juego de Tronos', autor:'George R.R. Martin'},
                {titulo:'I robot', autor:'Isaac Asimov'}
            ];
        });
        </script>

Restructurando un poco más el código mejor mediante un array de controlladores:

<script>
        var miApp = angular.module('miApp',[]);

        var controllers = {};
        controllers.miControlador = function($scope) {
            $scope.libros = 
            [
                {titulo:'El Juego de Ender', autor:'Orson Scott Card'},
                {titulo:'Juego de Tronos', autor:'George R.R. Martin'},
                {titulo:'I robot', autor:'Isaac Asimov'}
            ];
        });

        miApp.controller(controllers);

        </script>

Modules, Routes and Factories


Se puede ver este tour rápido en el famoso vídeo de Dan Wahlin de AngularJS Fundamentals In 60-ish Minutes