Componentes en AngularJS 1.5

  • Por
Desarrollo de components en Angular 1.5, en esta guía a la componetización aprenderás a realizar realizar tus propios componentes.

En el Manual de AngularJS no habíamos tratado todavía un asunto tan interesante y novedoso como es la creación de componentes, una nueva manera de realizar el tipo de trabajo que antes venía realizándose con las directivas. Hoy la alternativa de los componentes está conviviendo con las propias directivas, en la versión 1.x, aunque se prevé que las directivas finalicen definitivamente, y se sustituirán completamente por componentes en el nuevo Angular 2.0. Esto es debido a que los componentes y las directivas sirven más o menos para hacer las mismas cosas, extender el HTML con nuevas funcionalidades que se puedan implementar de manera declarativa. Sin embargo la orientación a componentes permite una mayor sencillez y versatilidad para el desarrollo.

En este artículo estudiaremos algunas diferencias entre componentes y directivas y veremos cómo realizar un componente sencillo, de modo que nuestra aplicación Angular sea capaz de conocer nuevas etiquetas de HTML. Usaremos la versión 1.5 de AngularJS, aunque desde hace menos tiempo han actualizado ramas anteriores de AngularJS (versión 1.3 en adelante) para que también admita desarrollo basado en componentes.

Directivas Vs componentes

Las directivas de AngularJS, así como los componentes se crean añadiendo la funcionalidad a un módulo (module) igual que otros elementos como controladores o factorías.

La diferencia fundamental es que, mientras que las directivas recibían una función, igual que controllers o factorys, los componentes reciben un objeto. Realmente es parecido en el sentido en el que las directivas al final debían devolver un objeto y los componentes directamente sirven ese objeto al método component().

Directivas se declaraban así:

.directive('nombre_directiva', function() {
  return {
    //...
  };
});

Los componentes por su parte se declaran:

.component('nombre_componente', {
    //...
});

Este es uno de los muchos detalles, puesto que muchos otros conceptos han sido simplificados con respecto a las directivas.

Pero en la práctica los componentes además nos permiten extender el HTML de otra manera, creando nuevas etiquetas completas que podremos incorporar y que esconden dentro sus propias complejidades, permitiendo una mayor reutilización y manteniendo encapsulada su complejidad.

Esto nos permite simplificar el marcado de las vistas. Si antes teníamos algo como:

<h2>Contactos</h2>
<ul class="lista">
    <li ng-repeat="elem in vm.contactos">
       {{elem.nombre}} <span>{{elem.telefono}}</span>
    </li>
</ul>

Ahora en resumen podremos tener algo como:

<contactos items="vm.contactos"></contactos>

El componente contactos encapsula todo ese marcado y a su vez podría estar usando otros componentes para encapsular cada uno de los contactos individuales, ya que unos componentes se apoyan en otros para resolver los problemas.

Si tenemos varias listas de contactos simplemente le pasamos un juego de datos distinto y listo. Si tenemos otro proyecto que maneje contactos, se hace mucho más cómodo reutilizar el componente. También permite aislar mejor los distintos componentes del proyecto entero, el scope y realizar testing de cada componente de manera independiente, entre otras ventajas con respecto a las directivas.

Crear componentes básicos

De momento vamos a aprender a crear componentes que no trabajan con datos, que simplemente encapsulan un marcado HTML, que ya es bastante. Así podremos aprender de una manera sencilla a crear componentes, incluirlos en nuestra aplicación y usarlos desde las vistas.

Simplificaremos al máximo el ejemplo, teniendo en cuenta que generalmente para facilitar la reutilización y la organización de archivos del proyecto, lo ideal sería colocar el componente en un archivo aparte, incluso su HTML separarlo a otro fichero independiente. Veremos aún en este artículo varias de estas mejoras.

Este es el Javascript de nuestro componente:

angular
  .module("appProbandoComponent", [])
  .component("probandoComponent", {
    template: [
      '<div class="miclase">',
      '<span>Esto es algo de HTML en el componente</span> ',
      '<b>Angular Rules!</b>',
      '</div>'
    ].join('')
  });

Lo importante que tienes que observar del código anterior:

  • Usamos el método component() para definir el componente. Ese método recibe el nombre del componente y el objeto que lo define.
  • El nombre del componente que pasamos a la función component debe estar escrito en "camel case", si es que está compuesto por varias palabras. Pero luego veremos que en el HTML nos referimos al componente separando las palabras por guiones.
  • En el objeto enviado al componente le indicamos el atributo "template" que tiene el HTML del marcado del componente. Luego veremos que existe un atributo llamado "templateUrl" que es más interesante por contener una ruta para un archivo HTML donde colocaremos el marcado de manera separada.

Y ahora veamos cómo se usaría:

<probando-component></probando-component>

Como ves es como si hubiésemos creado una nueva etiqueta, que el navegador entenderá perfectamente gracias a AngularJS. No obstante, por la construcción de nuestro ejemplo, donde estamos usando la inicialización básica de Angular, vamos a necesitar el ng-app en la etiqueta BODY o HTML. Mira el código html completo de nuestro ejemplo.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Probando componentes</title>
</head>
<body ng-app="appProbandoComponent">
  <probando-component></probando-component>

  <script src="bower_components/angular/angular.min.js"></script>
  <script>
  angular
  .module("appProbandoComponent", [])
  .component("probandoComponent", {
    template: [
      '<div class="miclase">',
      '<span>Esto es algo de HTML en el componente</span> ',
      '<b>Angular Rules!</b>',
      '</div>'
    ].join('')
  });
  </script>
</body>
</html>

Organizar los archivos de un componente

Repetimos, que no hemos usado muy buenas prácticas en este ejercicio, por simplificar las cosas y centrarnos simplemente en el método component() que nos permite crear el componente. Así que vamos a detenernos ahora en mejorar lo presente. La idea es estructurar los componentes en una carpeta específica del proyecto, además de separar el contenido de la presentación, etc.

Carpeta de componentes:
Como primera buena práctica, vamos a crear una carpeta donde colocaremos todos los componentes que vayamos desarrollando para nuestra aplicación.

A esta carpeta la llamaremos "components" y a su vez colocaremos dentro de ella cada componente en un directorio independiente.

Nuestro componente ahora se llama "mi-header". Dentro de nuestro proyecto lo colocaremos en la carpeta "componentes/mi-header". Dentro de esa carpeta vamos a crear dos archivos distintos, uno con el Javascript del componente y otro con el HTML, de modo que separaremos el contenido de la lógica.

En la siguiente imagen encuentras la propuesta de organización de archivos.

El Javascript del componente:
Ahora veamos nuestro Javascript para definir el componente. Lo más importante aquí es que hemos usado un módulo independiente para este componente. Sobre este "module" crearemos el componente en sí con el método component(). Lo interesante de esta alternativa es que para reutilizar el componente en otro proyecto será simplemente traernos este módulo y declararlo como dependencia.

Este sería nuestro archivo mi-header.js

angular.module("miHeader", [])
  .component("miHeader", {
    templateUrl: "./components/mi-header/mi-header.html"
  });

En esta ocasión comprobarás que en lugar del marcado del componente, definido con el atributo "template" que vimos antes, tenemos el atributo "templateUrl" donde indicamos la ruta del HTML del componente, desde la raíz de nuestro proyecto.

Marcado del componente:
El código HTML del componente ahora lo tenemos en un archivo .html, lo que nos ofrece muchas ventajas de cara al mantenimiento, como te imaginarás.

Este sería el código HTML de nuestro archivo mi-header.html

<header>
  <h1>Esta es mi cabecera</h1>
  <div>Controles de cabecera</div>
</header>

Declaramos la dependencia del componente en el módulo principal de la aplicación:
Lo hemos dicho antes, al estar el componente en un módulo independiente, en nuestro módulo principal de aplicación debemos declarar que estamos dependiendo de este componente.

Esto es lo que tenemos en app.js, que sería el Javacript principal de nuestra aplicación. Está vacío, salvo porque hemos declarado la dependencia con el módulo llamado "mi-header".

angular
  .module("appProbandoComponent", ["miHeader"])

Usamos el componente desde el index.html del proyecto:
Ahora nos queda usar el componente. Esto lo hacemos en el index.html, colocando la etiqueta del componente. Pero además recuerda definir el ng-app con el nombre del módulo principal de la aplicación, así como incluir los diferentes scripts.

Veamos el código completo de index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Probando componentes</title>
</head>
<body ng-app="appProbandoComponent">
  <mi-header></mi-header>

  <script src="bower_components/angular/angular.min.js"></script>
  <script src="components/mi-header/mi-header.js"></script>
  <script src="app.js"></script>
</body>
</html>

Todo este código también dependerá del gestor de dependencias que uses y el tipo de arranque que prefieras en tu aplicación Angular. Pero repara que para usar el componente simplemente colocamos la etiqueta HTML "mi-header".

<mi-header></mi-header>

De momento eso es todo. Seguramente podrás darte cuenta de las ventajas de la componetización en AngularJS. Ahora es empezar a usarla. No obstante, seguiremos informando sobre cómo realizar otras cosas con componentes, porque hasta ahora con lo que has visto solo son como "includes" de código HTML, y realmente podemos derivar mucha lógica de nuestra aplicación dentro de los componentes.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Mario Alcántara

25/2/2016
Componentes AngularJS
Quiere decir todo esto q la programación en AngularJS va a derivar en componetizacion. Hay que cambiar el chip poeque de momento estaba muy cómodo con las vistas en el html.

Maria Isabel

29/2/2016
Gracias
Muchas gracias por el articulo es una perspectiva muy interensante =) Ojala y detalle un poco mal el tema.

Sebastian

29/2/2016
Excelente
Gracias por el esfuerzo de mantener actualizado el manual sumando artículos. Esto muta constantemente y es importante tenerlo al día como lo vienen haciendo ustedes.