0% encontró este documento útil (0 votos)
92 vistas107 páginas

Angular e Book

Cargado por

Giancarlort
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
92 vistas107 páginas

Angular e Book

Cargado por

Giancarlort
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 107

4 desde Cero

La guía básica de introducción a este


poderoso framework.

SAPiens IT
Pedro Jiménez Castela
Angular 4 desde Cero
La guía básica de introducción a este
poderoso framework.

Escrito por Pedro Jiménez Castela


© 2.017 Sapiens IT

Todos los derechos reservados.


Queda prohibida la reproducción parcial o total de este libro, transmisión o envío de
copias.
El código utilizado en el libro puede ser empleado libremente por los compradores del libro
bajo su responsabilidad.
Publicado en Madrid, en Julio de 2.017
Gráficos empleados distribuidos libremente por www.freepik.es

¿Quieres convertirte en Desarrollador Web Full Stack y acceder


a miles de Empleos?

¡Este es tu curso!

Pulsa aquí para inscribirte ahora mismo por sólo 10 US $


(10 € en la Unión Europea)
*promoción válida durante dos días.

www.sapienslearning.com
SAPiens IT
Índice

1 TypeScript y Web Components 5


1.1 TypeScript 5
1.2 Instalación de TypeScript 5
1.3 Tipos de datos en TypeScript 6
1.3 Variables en TypeScript. 11
1.5 Clases en TypeScript. 13
1.6 Constructor en TypeScript 15
1.7 Interfaces en TypeScript 18
1.8 Web Components 20
2. Gestión de la configuración: Angular-Cli 21
2.1 Instalación 21
2.2 Requisitos Previos 21
2.3 Instalación de Angular CLI. 22
2.4 Creación de un Proyecto en Angular 22
2.5 Arranque de la Aplicación. 24
2.6 El Archivo index.html 24
2.7 El Archivo styles.css 26
2.8 El Archivo favicon.png 26
2.9 El Directorio Assets 27
3 Módulos y Componentes. 27
3.1 Módulos en Angular. 27
3.2 Componentes en Angular. 30
3.3 Creación de un nuevo componente 36
3.4 Creación de componente con Angular CLI. 40
3.5 Anidado de Componentes 42
4 Data Binding 45
4.1 Interpolación. 46
4.2 Property Binding. 50
4.3 Event Binding. 53
4.4 Two Way Binding 54
5 Directivas. 57
5.1 Directiva ngIf 58
5.2 Directiva ngStyle 62
5.3 Directiva ngClass. 64
5.4 Directiva ngFor 67
5.5 Directiva NgSwitch 71
5.6 Creación de directivas propias. 75

Página 1
5.7 Utilización de @Input entre componentes 79
5.8 Utilización de @Output entre componentes 84

Angular tiene cientos de funcionalidades que permiten convertirte en un


desarrollador web Full Stack. Inscríbete aquí a nuestro curso online.

Página 2
Página 3
Introducción

¡Hola! Mi nombre es Pedro y he escrito este libro para que aprendas de manera
práctica el increíble framework Angular, que nos permite crear aplicaciones
modernas en la nube, con todos los requisitos que demandan las empresas más
exigentes.

No necesitas más que unos ligeros conocimientos de HTML, JavaScript, CSS y


un equipo conectado a internet para convertirte en un desarrollardo full stack
con Angular. Si encuentras algún contenido que no conozcas, mándame un
email y te remito los mejores recursos gratuitos para aprenderlos.

¡Mil gracias y bienvenido!

Página 4
1 TypeScript y Web Components

1.1 TypeScript

Antes de comenzar a aprender Angular, vamos a conocer una serie de


pinceladas del lenguaje en el que esta basado, TypeScript.

TypeScript es un lenguaje de programación de distribución y código abierto


desarrollado por Microsoft. Su propio fabricante lo define como un superset
(superconjunto) de JavaScript que, en esencia, mejora JavaScript añadiéndole
funciones de tipado y de programación orientada a objetos.

Además, la sintaxis y desarrollo en TypeScript incorpora las mejoras y


características de ECMAScript 6, estandarización de JavaScript.

Debido a estas nuevas especificaciones, el framework Angular utiliza TypeScript


como lenguaje de programación para la lógica de las aplicaciones. Como las
características de ECMAScript 6 aún no son soportadas por los navegadores
web, el propio framework Angular ‘transpila’ el código TypeScript directamente
a JavaScript para que pueda ser interpretado en los clientes web.

Página 5
1.2 Instalación de TypeScript

Antes de instalar TypeScript y debido a que también es necesario para Angular,


debemos instalar Node Js y NPM. Al final del libro dispones de un anexo que
explica los pasos para su instalación.

Para instalar TypeScript, podemos emplear el gestor de paquetes NPM. De esta


manera, en la consola del equipo completamos:

npm install -g typescript

Para comprobar la correcta instalación o la versión de TypeScript en el caso de


que ya estuviera instalado, completamos en la consola:

tsc -v

Que nos devolverá la versión instalada y así tendremos nuestro equipo listo para
trabajar.

Página 6
1.3 Tipos de datos en TypeScript

Ya hemos dicho que una de las principales características de TypeScript es que


proporciona tipos de datos, siendo la sintaxis de declaración, tipo e inicialización
de variables globales, la siguiente:

let nombrevariable: tipodedato = valor;

De esta manera TypeScript soporta los siguientes tipos básicos de datos:

• Strings

let texto: String = ‘Cadena de caracteres’;

Que además, permite multilínea con comillas backsticks:

let textomulti: String = ` ACME S.A.


Paseo de la Castellana, 100
28.010 Madrid ` ;

• Números

let decimal: number = 6;


let hexadecimal: number = 0xf00d;
let binario: number = 0b1010;
let octal: number = 0o744;

• Arrays.

Que se declaran simplemente con corchetes y el tipo de dato de sus


elementos mediante:

let lista: number[] = [2,4,8];

o bien, de manera más expresiva mediante:

let lista: Array<number> = [1, 2, 3];

Página 7
• Any

Permite que la variable tome cualquier tipo de dato:

let cualquiera: any = 12;

let cualquiera = “¡Hola Mundo!”;

• Booleanos.

Obliga a seleccionar los valores booleanos true o false:

let booleano: true = 12;

Para más información sobre otros tipos de datos y su empleo, podemos


consultar la documentación de TypeScript en:

https://www.typescriptlang.org/docs/handbook/basic-types.html.

Vamos a practicar un poco de TypeScript en nuestro editor.

Si quieres utilizar Visual Studio Code, mi editor favorito, al final del libro
aprendemos a instalarlo y configurarlo.

En primer lugar, para comprobar los tipos de datos en TypeScript creamos un


directorio de nombre typestest, por ejemplo, en nuestro equipo. A
continuación, vamos a crear dos archivos de ejemplo. El primero, un clásico
archivo HTML denominado index.html con el siguiente código:

index.html

<!DOCTYPE html>
<html lang="es">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"
</head>

Página 8
<body>
<h1 id="encabezado"></h1> ①
<script type="text/javascript" src="test.js"></script> ②
</body>
</html>

En el cual:

① Hemos introducido un simple h1 con el id “encabezado”.

② Y referenciamos en una etiqueta script a un archivo JavaScript test.js.

Creamos un segundo archivo TypeScript denominado test.ts, con en el que


comenzamos escribiendo el siguiente código:

test.ts

let nombre: string = "Carlos"; ①

function saludo(nombre){
return "Hola "+nombre; ②
}
document.getElementById("encabezado").innerHTML = saludo(nombre); ③

En el cual:

① Declaramos la variable nombre y la inicializamos con el valor “Carlos”.

② Creamos una función saludo con el parámetro nombre que devuelve un


“Hola” más el nombre.

③ Y finalmente la inyectamos en el elemento “encabezado” del html con el


método JavaScript.

El fichero TypeScript como tal no lo podemos emplear en el html, de hecho en


el script hemos indicado un archivo js, ya que los navegadores no lo
reconocerían. Por tanto, lo tenemos que ‘transpilar’ a JavaScript.

Página 9
Para ello, en la consola de nuestro equipo, dentro de la carpeta typetest
tecleamos:

tsc test.ts

Y comprobamos en el editor como se ha creado un archivo JavaScript, con


algunos cambios respecto al archivo original, por ejemplo, observamos como la
palabra reservada let se ha convertido a var.

Ahora, cuando carguemos nuestro archivo index.html en el navegador


verificamos como imprime por pantalla el valor correctamente.

Vamos a continuación a realizar una serie de cambios, y para no tener que


‘transpilar’ manualmente. Añadimos, en la consola del equipo y en el directorio
que hemos creado para el ejemplo, typestest, el siguiente comando:

tsc –w test.ts

Podemos cambiar el valor de la variable nombre para comprobar como


‘transpila’ automáticamente.

¡Continuamos! Vamos a modificar ahora el código de test.ts de la siguiente


manera:

test.ts

function imprPantalla(a,b){
return a+b;
}

let a: number = 10;

let b: number = 5;

document.getElementById("encabezado").innerHTML = imprPantalla(a,b);

Página 10
Lógicamente este código imprimirá por pantalla el número 15. Pero si ahora
modificamos:

let a: number = “Jorge”;

La consola nos devolverá un error pues el valor Jorge no es un número.

Otra de las particularidades de TypeScript, es que se puede establecer el tipo


de dato que devolverá una función.

La sintaxis será la siguiente:

function nombreFuncion(parametros): tiposdedato {


//código de la función
}

Un sencillo ejemplo sería:

function devuelveEdad ( edad ): number {


let miEdad = edad;
return miEdad;
}

Página 11
1.4 Variables en TypeScript

Ya hemos adelantado en el apartado anterior, que en TypeScript las variables se


declaraban con la palabra reservada let.

Pero además, TypeScript permite también emplear la palabra reserva var como
en JavaScript, entonces… ¿cuándo emplear una u otra forma?

Pues dependiendo del alcance de la variable. Si necesitamos declarar la variable


de forma local al bloque de código, declaración o expresión donde se ejecuta
emplearemos let. En cambio si la declaración se necesita realizar de manera
global, emplearemos var.

Veamos un ejemplo a continuación.

Vamos a editar nuestro archivo TypeScript sustituyendo todo el código por el


siguiente:

test.ts

let a = 10; ①

if (true){

let a = 15 ②
console.log("Dentro del if a tiene un valor de "+a);
} else {
//
}

console.log("Fuera del if a tiene un valor de "+a);

En el cual:

① Declaramos la variable a y la inicializamos con valor 10.

② Creamos una estructura if-else donde cambiamos el valor de a a 15 y lo


imprimimos en la consola dentro del if (el else lo dejamos vacío).

③ Y finalmente, imprimimos el valor de a fuera del if-else.

Página 12
Comprobaremos en la consola del navegador, como arroja dos valores
diferentes de acuerdo al código que hemos programado:

Si ahora modificamos la declaración de la variable dentro del if utilizando la


palabra reservada var:

test.ts

var a = 10;

if (true){

var a = 15
console.log("Dentro del if a tiene un valor de "+a);
} else {
//
}

console.log("Fuera del if a tiene un valor de "+a);

Como la variable pasa a ser global, su valor dentro del if también se utiliza fuera
de esta y por tanto ambos logs muestran el mismo valor en la consola.

Página 13
1.5 Clases en TypeScript

En TypeScript disponemos de clases para crear objetos, consiguiendo de esta


manera que este lenguaje pueda ser orientado a objetos.

La sintaxis para crear clases será la siguiente:

class NombreClase {
public/private nombrepropiedad: tipo de dato;
….

public/private nombremetodo() {
//código del método
}

}

Por ejemplo, en nuestro archivo test.ts sustituimos todo el código para añadir:

test.ts

class Curso {
public titulo: string; ①
public descripcion: string;
public horas: number;
public inscritos: number;

public getInscritos() { ②
return this.inscritos;
}

public setInscritos(inscritos: number) {


this.inscritos = inscritos;
}

public addInscrito(){
this.inscritos++;
}

Página 14
public remInscrito() {
this.inscritos--;
}

var cursoAngular = new Curso(); ③

cursoAngular.setInscritos(9);
cursoAngular.addInscrito();

console.log(cursoAngular.getInscritos()); ④

En el cual:

① Declaramos cuatro propiedades públicas.



② Creamos cuatro métodos públicos para devolver el número de inscritos,
establecer el número de inscritos, añadir un nuevo inscrito y eliminar un inscrito.

③ Creamos un objeto cursoAngular de la clase Curso, establecemos el valor 9


en la propiedad inscritos con el método setInscritos y añadimos uno más con el
método addInscrito.

④ Imprimimos en la consola la cantidad de inscritos del cursoAngular.

Comprobamos el resultado esperado, en la consola del navegador:

Página 15
1.6 Constructor en TypeScript

También TypeScript permite el uso de constructores, siendo estos, métodos


para inicializar las propiedades o atributos de un clase.

La sintaxis es la siguiente:

class NombreClase {
public/private nombrepropiedad: tipo de dato;
….
constructor () {
this.nombrepropiedad = valor;

}

public/private nombremetodo() {
//código del método
}

}

Por ejemplo, podemos sustituir la clase anterior Curso por el siguiente código:

test.ts

class Curso {
public titulo: string;
public descripcion: string;
public horas: number;
public inscritos: number;
}

constructor() {
this.titulo = "Nombre del curso";
this.descripcion = "Lorem ipsum";
this.horas = 20;
this.inscritos = 0;
}

Página 16
public getInscritos() {
return this.inscritos;
}

public setInscritos(inscritos: number) {


this.inscritos = inscritos;
}

public addInscrito(){
this.inscritos++;
}

public remInscrito() {
this.inscritos--;
}

var cursoAngular = new Curso();

console.log(cursoAngular);

Comprobaremos en la consola del navegador como se ha creado este objeto


de la clase curso y sus variables han sido inicializadas con los valores por defecto
del constructor.

Página 17
También podemos emplear parámetros en el constructor. Para ello modificamos
por ejemplo el constructor de la siguiente forma.


constructor( titulo, descripcion, horas ) {
this.titulo = titulo;
this.descripcion = descripcion;
this.horas = horas;
this.inscritos = 0; //en este caso se establecerán con el método
}

Y sustituimos la línea de creación del objeto cursoAngular:


var cursoAngular = new Curso("Curso Angular","Lorem...",100);

De esta forma, el objeto se crea con los parámetros introducidos para cada
propiedad.

Si no disponemos de algún parámetro a la hora de crear el objeto, para evitar


errores de compilación, se puede emplear como valor undefined o null, de tal
manera que se introduzcan todos los parámetros y en el orden especificado.

Página 18
1.7 Interfaces en TypeScript

Para concluir con esta introducción a TypeScript, completamos el conocimiento


de la sintaxis básica para la creación de objetos con interfaces.

Las interfaces, nos permitirán obligar a definir clases con unas determinadas
propiedades o métodos.

Su sintaxis es:

interface NombreInterfaz {

nombrepropiedad: tipodedato;
nombreMetodo(): tipodedato;

Y se implementan en la clase:

class Nombredelaclase implements NombreInterfaz {



}

En el ejemplo anterior, añadimos antes de la clase en el archivo test.ts, el


siguiente código:

test.ts

interface DatosMaestros {
titulo: string;
addInscrito();
}

Modificamos la primera línea de la definición de la clase de la siguiente forma:


class Curso implements DatosMaestros {

}

Página 19
Y eliminamos la propiedad titulo en el constructor:


constructor( descripcion, horas ) {
this.descripcion = descripcion;
this.horas = horas;
this.inscritos = 0; //en este caso se establecerán con el método
}

Como la interfaz obliga a implementar la clase con todas sus propiedades, la


consola nos devolverá un error:

El resto de características básicas de TypeScript pueden ser consultadas en su


documentación:

https://www.typescriptlang.org/docs/home.html

Página 20
1.8 Web Components

Los web components son un estándar del W3C, que permiten componer el
desarrollo de aplicaciones web a partir de contenedores dedicados a una cierta
funcionalidad. Estarán compuestos por archivos con el lenguaje de marcado
HTML5, con código JavaScript para la lógica de negocio y con hojas de estilo
CSS para la presentación.

Cada uno de estos componentes se puede implementar en el código de las


páginas HTML5 a través de una etiqueta específica, que renderizará el
componente y su funcionalidad, con una sintaxis muy simple:

<nombre-del-componente></nombre-del-componente>

Los web components pueden estar compuestos de 4 elementos:

• Templates. Son plantillas HTML5 con el contenido del componente.

• Custom Elements. Permiten la definición de elementos HTML propios.

• Shadow DOM. Podría definirse como un elemento DOM ajeno al DOM


de la página web el cual encapsula el componente.

• HTML Imports. Líneas de código para en HTML, importar los ficheros


HTML que contengan los componentes.

Angular, desde su primera versión a la actual, utiliza los web components como
tecnología para el desarrollo de aplicaciones web, como veremos a lo largo de
todo el libro.

Para más información sobre esta tecnología, su documentación se encuentra


en:

https://developer.mozilla.org/es/docs/Web/Web_Components

Página 21
2. Configuración de proyectos: Angular-Cli

2.1 Instalación

Angular más que un framework, es toda una plataforma en la que crear


aplicaciones web. Los proyectos en Angular, no se crean como una estructura
de archivos estáticos, si no que necesitan una instalación en Node JS para tener
un pequeño servidor y también cientos de dependencias para su uso en este
servidor, por ejemplo las que traducen los archivos TypeScript que escribiremos,
a los archivos Javascript que empleará el navegador.

Realmente Angular no se instala en un equipo local de manera global (aunque


podría hacerse) sino que se añade como módulos Node a cada proyecto que
creemos con este framework.

De esta manera, la forma de instalación hasta la versión 2, fue añadir un archivo


package.json e instalarlo con el gestor de paquetes NPM.

Aunque es posible seguir implementando Angular a nuestros proyectos a partir


de un archivo package.json, en la actualidad disponemos una herramienta de
línea de comandos, Angular CLI, que realizará ese trabajo por nosotros así como
otras funcionalidades más que conoceremos posteriormente.

Página 22
2.2 Requisitos Previos

Una vez que instalemos Node JS y NPM, comprobamos en la consola sus


versiones con los comandos:

node –v

npm –v

Ambas tienen que ser superiores a v5.x.x y 3.x.x respectivamente.

2.3 Instalación de Angular CLI

La instalación de Angular CLI se lleva a cabo mediante NPM con el siguiente


comando en la consola del equipo:

npm install –g @angular/cli

La opción –g es para instalarlo de manera global.

Si queremos actualizar una instalación previa de Angular CLI, emplearemos:

npm uninstall -g angular-cli @angular/cli

npm cache clean

npm install -g @angular/cli

Página 23
2.4 Creación de un Proyecto en Angular

Una vez instalado Angular CLI, para crear un nuevo proyecto, nos situamos en
el directorio en el que queremos crear el proyecto en la consola y tecleamos:

ng new appCurso

El proceso concluirá pasados unos minutos y tras finalizar, podemos acceder al


directorio raíz del proyecto mediante:

cd appCurso

También podemos comprobar la estructura del proyecto creada por Angular CLI
en el editor que empleemos para el desarrollo de nuestra aplicación.

De momento y sin entrar en más detalles podemos fijarnos en el archivo


package.json que contendrá las dependencias del proyecto y su número de
versión.

En la creación del proyecto, Angular CLI, además de generar este archivo lo


instala mediante NPM.

Página 24
También nos podemos fijar como a partir de este package.json, se ha creado
una carpeta de módulos Node JS denominada node_modules, que contiene
todo el código del framework Angular en forma de paquetes, que emplearemos
en nuestra aplicación.

Este formato permite que cada módulo y componente llame al paquete de


Angular que vaya a utilizar y por tanto, solo cargue el código necesario para la
funcionalidad que necesite.

Por último, disponemos de un directorio src (por source) donde estará el código
de nuestra aplicación. El resto de archivos y directorios serán tratados más
adelante.

Página 25
2.5 Arranque de la Aplicación

Para levantar el servidor Node JS de nuestro nuevo proyecto, simplemente


desde el directorio raíz del mismo, tecleamos en la consola del equipo:

ng serve

De esta manera, se inicia el servidor en nuestro equipo y podremos acceder a la


aplicación en nuestro navegador en la siguiente url:

localhost:4200

Nota: Para usar un puerto diferente, se puede emplear:

ng serve --port <número del puerto>

Al acceder a la url, la aplicación nos muestra una plantilla de bienvenida, creada


por Angular CLI.

Página 26
2.6 El Archivo index.html

Como cualquier aplicación o sitio web, los proyectos Angular disponen de un


archivo index.html, ubicado en la carpeta src.

Además del código habitual de un archivo html, este archivo se caracteriza por
incluir la etiqueta <app-root></app-root>, que será la etiqueta del web
component donde se ‘renderice’ todo el código de la aplicación.

Dentro de la etiqueta raíz anterior, podemos añadir un texto que indique que la
aplicación está cargando o bien un spinner, que se mostrará durante la carga de
la aplicación si esta se demora.

Por ejemplo:

src/index.html


<app-root><p>Cargando aplicación…</p></app-root>

Si la aplicación es muy ligera, cargará tan rápido el componente raíz, que ese
texto de carga, directamente no se mostrará.

En la etiqueta <head></head> de este archivo, podemos añadir como en


cualquier otra aplicación, CDN de librerías de fuentes e iconos así como
frameworks de estilo como por ejemplo Bootstrap 4.

Por ejemplo, nosotros vamos a emplear las fuentes Google y Bootstrap 4, para
lo cual añadimos, dentro del <head></head>:


<link href="https://fonts.googleapis.com/css?family=Open+Sans"
rel="stylesheet">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-
alpha.6/css/bootstrap.min.css" integrity="sha384-

Página 27
rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNU
wEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"
integrity="sha384-
A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed95
0n" crossorigin="anonymous"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"
integrity="sha384-
DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51
bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-
alpha.6/js/bootstrap.min.js" integrity="sha384-
vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn
" crossorigin="anonymous"></script>

Si no queremos usar un CDN, otra forma de añadir Bootstrap a un proyecto


Angular es a través de la instalación mediante NPM.

Para en nos situamos en la consola del equipo, en el directorio raíz de la


aplicación y pulsamos:

npm install –save bootstrap

Una vez instalado, lo importamos en el archivo .angular-cli.json mediante la


modificación del código:

.angular-cli.json


styles: [
“../node_modules/bootstrap/dist/css/bootstrap.min.css”,
“styles.css”
]

Página 28
2.7 El Archivo styles.css

En el archivo styles.css, ubicado en la carpeta src, se pueden incluir todos los


estilos CSS globales a toda la aplicación, sin tener que incluir una llamada al
mismo en el index.html, ya que Angular lleva a cabo su carga de manera
automática.

2.8 El Archivo favicon.png

También en la carpeta src, se puede sustituir el archivo favicon.png existente,


que contiene el logo de Angular, por uno específico de nuestra aplicación en
las dimensiones habituales de este elemento.

Un recurso para crear nuestro favicon de manera online es:

http://www.genfavicon.com/es/

2.9 El Directorio Assets

Dentro del directorio src de la aplicación, en el directorio assets ubicaremos


todos los ficheros estáticos de la aplicación, sobre todo las imágenes, logos,
videos, etc, que empleemos en la misma.

Página 29
3 Módulos y Componentes

Las aplicaciones actuales basan su desarrollo en arquitecturas compuestas por


módulos que estructuren y organicen el código por funcionalidad y que al ser
reutilizables, reduzcan los costes de desarrollo.

Por supuesto, Angular también se caracteriza por emplear esas condiciones de


modularidad.

3.1 Módulos en Angular

Un módulo en Angular, es un conjunto de código dedicado a un ámbito


concreto de la aplicación, o una funcionalidad específica.

En Angular, los módulos se definen mediante una clase decorada con


@NgModule.

Toda aplicación de Angular tendrá al menos un módulo, el llamado módulo


principal o raíz (root module), que, para el caso de aplicaciones pequeñas será
único.

Los módulos, se definen en archivos TypeScript y podemos decir que están


compuestos de tres bloques o apartados de código.

Página 30
1. En primer lugar una serie de instrucciones de importación de las librerías
o paquetes Angular, asi como otros elementos externos que
emplearemos en el módulo.

2. En segundo lugar, @NgModule, un decorador que recibe un objeto de


metadatos que definen el módulo. Estos metadatos son los siguientes:

• Declarations. Las declaraciones son las llamadas vistas de un módulo.


Hay 3 tipos de vistas o declaraciones, los componentes, las directivas
y los pipes.

• Imports. En este apartado se indican las dependencias o paquetes


que empleará este módulo, cuyo origen se define en las
importaciones al inicio del archivo.

• Providers. Son los servicios utilizados por el módulo, disponibles para


todos los componentes, y que centralizan la gestión de datos o
funciones para inyectarlos en los componentes.

• Bootstrap. Este metadato define la vista raíz de la aplicación y es


utilizado solo por el módulo raíz. No confundir con el popular
framework de estilos del mismo nombre.

3. Y el tercer y último bloque de código, es la instrucción de exportación


del módulo como una clase Angular, que será posteriormente
introducido en el archivo JavaScript principal de la aplicación.

Insistimos en que en todas las aplicaciones Angular, existe al menos un módulo


raíz, que se encuentra ubicado en el archivo app.module.ts generado por
Angular CLI en el directorio src/app.

Página 31
Si nos fijamos en el código del archivo app.module.ts está compuesto de los
tres bloques de código detallados en el párrafo anterior.

src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';


import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';

@NgModule({
declarations: [
AppComponent
], ②
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})

export class AppModule { } ③

① Los import de las librerías de Angular necesarias para el funcionamiento de


este módulo así como el import del componente de este módulo.

② El decorador @NgModule, que incluye:

• Las declaraciones, con el componente AppComponent que a


continuación detallaremos.

• Los imports, con los módulos a emplear ( de momento el de renderización


en navegadores y el de formularios ambos de las librerías Angular ).

• Los providers, que se declaran como un array, y de momento está vacío


porque aún no hemos creado ningún servicio.

Página 32
• Y bootstrap, recordamos exclusivo de este módulo raíz, que define el
componente AppComponent para inicializar la aplicación.

③ Para finalizar, el archivo exporta la clase AppModule.

3.2 Componentes en Angular

Podemos definir un componente como una clase Angular que controla una parte
de la aplicación, de ahí que sean englobados como un tipo de vista.

Los componentes son definidos con el decorador @Component, y son los


archivos en los cuales definiremos y controlaremos la lógica de la aplicación, su
vista HTML y el enlace con otros elementos.

Un componente estará también compuesto por tres bloques de código:

1. Imports. Las sentencias de importación de los diferentes elementos que


empleará el componente.

2. Decorador @Component. Con al menos, los siguientes metadatos:

Selector. Que define la etiqueta html donde se renderiza el componente.

Template. El archivo html con la vista del componente.

Style. Con el archivo CSS con los de estilos del componente.

3. Export de la Clase. Definición y exportación de la clase con la lógica del


componente.

El módulo raíz, como hemos detallado anteriormente, dispone también de un


componente obligatorio para el funcionamiento de la aplicación. Se trata del
archivo TypeScript app.component.ts y se encuentra en el directorio app.

Podemos observar en su código, generado por Angular CLI al crear el proyecto,


los tres bloques de código:

Página 33
src/app/app.component.ts

import { Component } from '@angular/core'; ①

@Component({
selector: 'app-root',
templateUrl: './app.component.html', ②
styleUrls: ['./app.component.css']
})

export class AppComponent { ③


title = 'app';
}

En el cual:

① Se escriben los imports del componente, en este caso de la librería


Component de Angular.

② El Decorador @Component, con un objeto de metadatos, que en este caso


contiene:

• El selector. Que define en qué etiqueta html se renderizará este


componente. En este componente raíz, la etiqueta es app-root que es la
que tenemos en el archivo index.html.

• La template o plantilla. Que define el contenido html del componente.


En este caso se usa templateUrl y la ruta del archivo template, siendo
app.component.html.

• La referencia de estilo. Aquí se definen los estilos CSS particulares de ese


componente. En este caso se usa styleUrls y la ruta del archivo de estilo
del componente, siendo app.component.css.

③ Exportación de la clase AppComponent que contiene la lógica del


componente. Vemos como en este caso, simplemente define una variable ‘title’
a la que asigna un texto con el valor ‘app’.

Página 34
Veamos a continuación el funcionamiento del componente incluido en el
módulo raíz.

El componente define mediante templateUrl, cual es el archivo template HTML,


en este caso app.component.html, que se encuentra en su misma carpeta, y
cuyo código es:

src/app/app.component.html

<div style="text-align:center">
<h1>
Welcome to {{title}}!!
</h1>
<img width="300" src="…” />
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank"
href="https://angular.io/docs/ts/latest/tutorial/">Tour of Heroes</a></h2>
</li>
<li>

</li>
</ul>

Vemos como se trata de un archivo html pero sin la estructura de página web,
ya que se inyectará en en el archivo index.html. Además de las etiquetas html y
los textos, el código incorpora la variable title mediante la sintaxis moustache {{
title }}, de tal forma que esta sintaxis lo enlaza componente y mostrará en
pantalla el valor definido en la clase de este.

Además de definir la plantilla HTML, el componente también define con el


metadato selector, en qué etiqueta se renderizará su contenido, en este caso la
etiqueta con nombre app-root.

Página 35
Repetimos que el componente se exporta mediante la clase AppComponent,
que es importada en el módulo app.module.ts e incluida dentro de su decorador
en las declaraciones:

src/app/app.module.ts


import { AppComponent } from './app.component';


declarations: [
AppComponent
],

Por otra parte, este archivo de módulo app.module.ts es el módulo raíz e incluye
en el decorador la propiedad Bootstrap igualada al componente, para
finalmente exportar todo el módulo con la clase AppModule:

bootstrap: [AppComponent]
})
export class AppModule { }

¿Dónde empleamos esta clase del módulo que se exporta? En otro archivo
situado en la raíz de la aplicación, denominado main.ts.

src/main.ts

import { enableProdMode } from '@angular/core';


import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module'; ①


import { environment } from './environments/environment';

Página 36
if (environment.production) {
enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule); ②

Que ① importa AppModule y en su última línea ② define AppModule como


el punto de entrada de la aplicación.

Finalmente, el archivo index.html contiene dentro del body, la etiqueta <app-


root>, donde renderizará la plantilla del componente.

src/index.html


<body>
<app-root></app-root>
</body>

Lo podemos comprobar si inspeccionamos el elemento en el navegador con las


herramientas de desarrollador:

Página 37
Otra forma práctica de comprobarlo, es sustituir totalmente el contenido del
archivo app.component.html por un mítico ‘¡Hola Mundo!’:

src/app/app.component.html

<div style="text-align:center">
<h1>¡Hola Mundo!</h1>
</div>

Y al acceder ahora a nuestro navegador en localhost:4200 nos mostrará:

También podemos comprobar la lógica de la aplicación sustituyendo en el


archivo app.component.ts las expresiones en la clase por la siguiente:

src/app/app.component.ts


export class AppComponent {
destino: string = 'Universo';
}

Y a continuación, modificamos de nuevo el archivo app.component.html,


sustituyendo todo el código por el siguiente:

src/app/app.component.html

<div style="text-align:center">
<h1>¡Hola {{ destino }}!</h1>
</div>

Página 38
Volvemos al navegador y comprobamos:

Es importante recordar que la sintaxis de Javascript/Typescript está capitalizada


y distingue mayúsculas de minúsculas.

También podemos hacer uso del archivo de estilos CSS del componente,
app.component.ts, en el que por ejemplo escribir la siguiente clase:

src/app/app.component.css

.encabezado {
text-align: center;
color: blueviolet;
}

De nuevo modificamos el archivo de la plantilla, app.component.html,


sustituyendo todo el código por el siguiente:

src/app/app.component.html

<div class="encabezado">
<h1>¡Hola {{ destino }}!</h1>
</div>

Y comprobamos en el navegador como se han aplicado los estilos:

Página 39
3.3 Creación de un nuevo componente

Una vez que conocemos el funcionamiento de un componente, concretamente


el raíz, vamos a crear un nuevo componente y veremos cómo, aunque su
funcionamiento es idéntico, su integración en la aplicación es diferente a la del
componente raíz.

Aunque se pueden crear con Angular CLI, para crear un nuevo componente de
manera manual, en primer lugar creamos un directorio con el nombre
identificativo del componente, por ejemplo, fechaactual, en el directorio src/app
de la aplicación.

Dentro del componente creamos de momento dos archivos, el template con el


nombre fechaactual.component.html y el archivo TypeScript
fechaactual.component.ts.

La forma de nombrar los archivos es opcional, pero como buena práctica o


convención, se usa el nombre del componente seguido de punto, la palabra
component y la extensión del archivo, como así ocurre con el componente raíz.

Dentro el archivo fechaactual.component.ts escribimos el siguiente código:

src/app/fechaactual/fechaactual.component.ts

import { Component } from '@angular/core';

@Component({
selector: 'app-fechaactual', ①
templateUrl: './fechaactual.component.html' ②

Página 40
})

export class FechaactualComponent {


hoy: any = new Date(); ③
}

Dentro del código, comprobamos como hemos declarado ① app-fechaactual


en el selector, ② hemos definido el archivo de plantilla en templateUrl y ③
hemos creado y exportado la clase FechaactualComponent con una sencilla
instrucción JavaScript que declara hoy como la fecha actual.

Además para las referencias a archivos, es importante observar, cómo se


emplean rutas relativas desde el directorio en el que se encuentre nuestro
archivo para llamar a otros archivos.

Ahora completamos la plantilla, en el archivo fechaactual.component.hmtl con


un sencillo código:

src/app/fechaactual/fechaactual.component.html

<p> Sevilla, {{ hoy | date:'d/M/y H:m' }} </p>

Además de la variable hoy, estamos añadiendo un pipe para dar formato de


fecha, funcionalidad de Angular que conoceremos más adelante.

El trabajo aún no ha finalizado, ya que necesitamos incorporar al módulo raíz


de la aplicación para poder utilizarlo.

Para ello, en primer lugar incluimos nuestro componente en el módulo


app.module.ts modificando el código de la siquiente manera:

src/app/app.module.ts


import { FechaactualComponent } from './fechaactual/fechaactual.component'; ①

Página 41

declarations: [
AppComponent,
FechaactualComponent ②
],

① Importamos la clase FechactualComponent con la ruta a nuestro archivo


(sin la extensión).

② Y en el array de declaraciones la añadimos.

Con esto, nuestro componente queda listo para ser utilizado, y por tanto
tenemos que añadir la etiqueta <app-fechaactual> donde queramos que se
renderice.

En el componente raíz, su etiqueta era directamente situada en el archivo


index.html, pero en el caso de otro componente del módulo que no sea el raíz
debemos situarlo en la plantilla de este módulo, para organizar correctamente
los componentes.

Por tanto, sustituimos el código de app.component.html de la siguiente manera:

src/app/app.component.html

<div class="encabezado">
<h1>¡Hola {{ destino }}!</h1>
<app-fechaactual></app-fechaactual>
</div>

Y ahora veremos en nuestro navegador, el código del componente raíz e


inmediatamente debajo el código del componente fechaactual:

Página 42
Si el código html de la vista del componente es pequeño, como es nuestro caso,
podemos simplificar la aplicación, eliminando el archivo
fechactual.component.html, añadiendo el código de este en el componente
mediante el metadado template.

Por ejemplo, en nuestro caso podemos sustituir en fechaactual.component.ts el


decorador por el siguiente:

src/app/fechaactual/fechaactual.component.ts

@Component({
selector: 'app-fechaactual',
template: `
<p> Sevilla, {{ hoy | date:'d/M/y H:m'}}</p>
`
})

En el que empleamos template en lugar de templateUrl y las comillas backstick


para delimitar el código html, permitiendo emplear multilínea.

Ahora eliminamos el archivo fechaactual.component.html pues ya no será


necesario y el funcionamiento sigue siendo el mismo.

Página 43
3.4 Creación de componente con Angular CLI

Una de las funcionalidades de Angular CLI es la de generar los archivos de, entre
otros, un componente, evitándonos tener que escribir el código común como
hicimos en el apartado anterior.

La sintaxis del comando para generar nuevos componentes es:

ng generate component <nombredelcomponente>

o su versión abreviada:

ng g c <nombredelcomponente>

Para crear un nuevo componente, nos situamos en la consola del equipo en el


directorio raíz del proyecto y completamos por ejemplo:

ng generate component copyright

Ya en la propia consola vemos como se crean los nuevos archivos y se actualiza


el módulo app.module.ts.

Además de los archivos que conocemos, se crea un archivo component.spec.ts


solamente para tareas de testing.

Si no queremos que se cree el archivo spec, podemos añadir en el comando


anterior de Angular CLI la opción --spec false. En nuestra nueva carpeta
copyrigth accedemos al archivo copyright.component.ts y añadimos el
siguiente código a la clase:

Página 44
src/app/copyright/copyright.component.ts

export class CopyrightComponent implements OnInit {

copyright: String = '© ACME S.A.';


hoy: any = new Date();

constructor() { }

ngOnInit() {
}

Más adelante hablaremos del método ngOnInit y del uso del constructor
JavaScript en Angular.

El siguiente paso será incluir el código en el template


copyrigth.component.html, por ejemplo:

src/app/copyright/copyright.component.html

<p> {{ copyright }} {{ hoy | date:'y' }} </p>

Y finalmente añadimos la etiqueta en el template del componente raíz


app.component.html:

src/app/app.component.html

<div class="encabezado" >


<h1>¡Hola {{ destino }}!</h1>
<app-fechaactual></app-fechaactual>
<app-copyright></app-copyright>
</div>

Página 45
Podemos comprobar en el navegador la correcta implementación del
componente.

Página 46
3.5 Anidado de Componentes

Los componentes pueden ser anidados, es decir que la etiqueta donde se


renderiza definida por el selector, puede ser empleada en cualquier parte del
código.

Por ejemplo dentro del template del componente copyright, podemos sustituir
el código para incluir la etiqueta del componente fechaactual:

src/app/copyright/copyright.component.html

<app-fechaactual></app-fechaactual>
<p> {{ copyright }} {{ hoy | date:'y'}} </p>

Y eliminar la etiqueta del código del template raíz app.component.html, para


que no se duplique:

src/app/app.component.html

<div class="encabezado" >


<h1>¡Hola {{ destino }}!</h1>
<app-copyright></app-copyright>
</div>

Siendo el resultado final el mismo.

Otra forma de anidado es incluir la etiqueta de un componente en el decorador


de otro. Por ejemplo, modificamos el archivo copyrigth.component.html para
dejarlo como estaba originalmente.

Página 47
src/app/copyright/copyright.component.html

<p> {{ copyright }} {{ hoy | date:'y' }} </p>

Y ahora modificamos el archivo fechaactual.component.ts para incluir en el


decorador la etiqueta del componente copyright:

src/app/fechaactual/ fechaactual.component.ts


@Component({
selector: 'app-fechaactual',
template: `
<p> Sevilla, {{ hoy | date:'d/M/y H:m'}}</p>
<app-copyright></app-copyright>
`
})

Y dejamos en el componente raíz, en su template app.component.html,


solamente la etiqueta del componente fechaactual:

src/app/app.component.html

<div class="encabezado" >


<h1>¡Hola {{ destino }}!</h1>
<app-fechaactual></app-fechaactual>
</div>

Página 48
El resultado en el navegador vuelve a ser de nuevo el mismo, por lo que
comprobamos que disponemos en Angular de la máxima flexibilidad a la hora
de estructurar los diferentes componentes de la aplicación.

Página 49
4 Data Binding

Podemos definir el data binding en Angular como la comunicación o el enlace


de datos entre el archivo Typescript del componente y el archivo HTML de su
template.

De hecho, ya hemos conocido el funcionamiento de la forma más sencilla de


este enlace, entre una variable declarada en la clase del componente y la
representación de su valor en la plantilla HTML mediante la sintaxis moustache
con doble llave.

Disponemos de varias formas de llevar a cabo los procesos data binding.

En primer lugar tenemos los data binding de tipo One Way de la fuente de datos
(archivo TypeScript) a la vista (archivo HTML). Dentro de este tipo se incluyen:

• Interpolación.

• Property Binding.

En segundo lugar se incluyen los de tipo One Way de la vista a la fuente de


datos:

• Event Binding.

Y finalmente, los que enlazan en ambos sentidos y simultáneamente los datos,


de la vista a la fuente de datos y viceversa, que se engloban en la siguiente
denominación.

• Two-way Binding.

Página 50
4.1 Interpolación

La interpolación, también denominada String Interpolation, consiste en incluir


dentro del código html y entre dobles paréntesis, una expresión que Angular
evalúa para mostrar en la plantilla.

Recordamos que este ha sido el procedimiento que empleamos en el apartado


anterior, cuando explicábamos el funcionamiento de los componentes.

Y recordamos su sintaxis, en la que se puede incluir una propiedad, un objeto o


una expresión JavaScritp entre dobles llaves, conocidad como sintaxis
moustache:

{{ propiedad/objeto/expresión }}

En los apartados anteriores, hemos utilizamos variables en la clase del


componente para después imprimirlas por pantalla en la plantilla HTML.

También podemos emplear la interpolación utilizando propiedades de un


objeto del componente como origen de los datos o cualquier expresión
JavaScript como tendremos la oportunidad de comprobar.

Vamos a ver un ejemplo de interpolación empleando objetos, pero antes de


conocer esta interpolación, vamos a ver como incorporar las clases para crear
objetos en Angular.

Una de las formas para crear objetos en Angular es mediante un modelo, es


decir, podemos crear un archivo en el que declarar la clase y sus propiedades
para posteriormente poder utilizar está clase en los componentes, de ahí que
denomine a estos archivos como modelos.

Vamos a crear una clase que se pueda utilizar en toda la aplicación. En primer
lugar creamos un directorio llamado modelos en el directorio app de la
aplicación.

Seguidamente, dentro de este directorio, creamos de manera manual un archivo


TypeScript denominado alumno.modelo.ts con el siguiente código:

Página 51
src/app/modelos/alumno.modelo.ts

export class Alumno {


public id: number;
public nombre: string; ①
public apellidos: string;
public ciudad: string;

constructor (id: number, nombre: string, apellidos: string, ciudad: string){


this.id = id;
this.nombre = nombre;
this.apellidos = apellidos; ②
this.ciudad = ciudad;

}
}

En el cual:

① Definimos las propiedades de la clase Alumno que se genera y exporta.

② Y usamos el método constructor para definir los parámetros que recibirá y


el enlace con las propiedades de la clase.

Este archivo no se enlazará en el módulo de la aplicación, app.module.ts,


porque de hecho no es ningún tipo de declaración ni tiene ningún decorador,
solamente exporta la clase Alumno para poder crear objetos de esa clase en
cualquier archivo de la aplicación.

A continuación vamos a ver como utilizamos esa clase Alumno en un nuevo


componente. Para ello, en la consola del equipo, en el directorio raíz del
proyecto, completamos:

ng g c viewmodelo –spec false

Página 52
Dentro de la clase de este nuevo componente en el archivo
viewmodelo.component.ts, importamos la clase Alumno y creamos un objeto
de esta clase llamado alumno1, de la siguiente manera:

src/app/viewmodelo/viewmodelo.component.ts


import { Alumno } from '../modelos/alumno.model';


export class ViewmodeloComponent {
alumno1 = new Alumno (1, 'Juan', 'Gutiérrez', 'Madrid'); } …

Ahora podemos añadir en la plantilla, en el archivo


viewmodelo.component.html, el código necesario para mostrar el objeto de la
siguiente forma:

src/app/viewmodelo/viewmodelo.component.html

<div class="container">
<h4>Información del Alumno</h4>
<hr>
<h5>id: {{ alumno1.id }}</h5>
<hr>
<h5>Nombre: {{ alumno1.nombre }}</h5>
<hr>
<h5>Apellidos: {{ alumno1.apellidos }}</h5>
<hr>
<h5>Ciudad: {{ alumno1.ciudad }}</h5>
<hr>
</div>

Página 53
En el que empleamos, dentro de la interpolación, la sintaxis de la notación del
punto JavaScript para mostrar el valor de la propiedad de un objeto:

nombredelobjeto.propiedaddelobjeto

Finalmente añadimos la etiqueta del componente en el archivo


app.component.html para renderizarla en nuestra aplicación:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de Interpolación con Objeto</h3>
<hr>
<app-viewmodelo></app-viewmodelo>
</div>

Y comprobamos en el navegador el resultado:

Otra opción de uso de la funcionalidad de interpolación es emplear métodos


para enlazar datos del componente a la vista.

En un ejemplo muy sencillo, vamos a crear un componente llamado ejmetodo


en el directorio raíz de la aplicación, tecleando para ello en la consola del
equipo:

ng g c ejmetodo --spec false

Página 54
Y una vez creado, añadimos a la clase del componente en
ejmetodo.component.ts el siguiente código:

src/app/ejmetodo/ejmetodo.component.ts


puntuacion = 9;

getPuntuacion() {
return this.puntuacion;
}

Ahora en la template del archivo ejmetodo.component.html sustituimos el


código por:

src/app/ejmetodo/ejmetodo.component.html

<p> La puntuación obtenida por la mayoría


de desarrolladores de Angular es de {{ getPuntuacion() }} sobre 10</p>

Y en el archivo app.component.html sustituimos el código para añadir la


etiqueta app-ejmetodo:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de Interpolación con Método</h3>
<hr>
<app-ejmetodo></app-ejmetodo>
</div>

Página 55
Comprobamos en el navegador como se carga correctamente:

Página 56
4.2 Property Binding

Property Binding es el segundo tipo de data binding empleados por Angular


para enlazar valores de la fuente de datos a la vista.

En este caso, se trata de un enlace que relaciona un atributo con una expresión,
con la siguiente sintaxis:

[ atributodelelementoHTML ] = “ expresión “

Vamos a crear un nuevo componente, ejpropertybinding, para lo cual como es


habitual, tecleamos desde la consola del equipo en el directorio raíz de la
aplicación:

ng g c ejpropertybinding --spec false

En el template, ejpropertybinding.component.html, sustituimos todo el código


por el siguiente:

src/app/ejpropertybinding/ejpropertybinding.component.html

<input type="text" placeholder="Escribe algo...">

Y colocamos la etiqueta del componente en el template del componente raíz en


app.component.html como en los casos anteriores, de la siguiente manera:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de Property Binding</h3>
<hr>
<app-ejpropertybinding></app-ejpropertybinding>
</div>

Página 57
Hasta ahora nada de particular, pero vamos a ver cómo modificar el
comportamiento del atributo placeholder de manera dinámica mediante
property binding.

En la clase del componente en ejpropertybinding.component.ts, añadimos el


siguiente código:

src/app/ejpropertybinding/ejpropertybinding.component.ts


texto = 'Escribe algo'; ①

constructor() {
setTimeout(() => {
this.texto = 'por favor'; ②
}, 3000);
}

El dinamismo de este código consiste en ① crear una propiedad texto


inicializada con el valor ‘Escribe algo…’ y a continuación, ② utilizar dentro del
constructor, para no tener que ser llamado, el método JavaScript setTimeout()
que llevará a cabo el código para cambiar el valor ‘Escribe algo…’ de la
propiedad texto a ‘por favor’ cuando pasen 3000 ms, es decir 3 segundos.

Ahora en el template modificamos el atributo, de manera que lo rodeamos de


corchetes y lo igualamos a la propiedad texto:

src/app/ejpropertybinding/ejpropertybinding.component.html

<input type="text" [placeholder]="texto">

Página 58
Y comprobaremos como, al iniciar el navegador, el input tendrá el texto “Escribe
algo” en su placeholder, y cuando transcurran 3 segundos, pasará a ser “por
favor”.

Página 59
4.3 Event Binding

Los enlaces event binding son enlaces de un solo sentido, one way, pero en este
caso desde la vista a la fuente de datos, ya que como su nombre indica, los
desencadena un evento en el cliente web.

En este enlace de datos, se iguala un evento de un elemento HTML de la vista


con una expresión, normalmente un método definido en la clase del
componente.

La sintaxis tiene la siguiente forma:

evento=”nombreMetodo()”;

Vamos a crear otro ejemplo como venimos haciendo, en un nuevo componente.


Para ello, tecleamos desde la consola del equipo en el directorio raíz de la
aplicación:

ng g c ejeventbinding --spec false

En la template, archivo ejeventbinding.component.hmtl, vamos a crear un botón


y un texto con el siguiente código:

src/app/ejeventbinding/ejeventbinding.component.html

<button class="btn btn-success"


(click)="modTexto()">Modificar Texto</button> ①
<h3> {{ texto }} </h3> ②

En el cual:

① El botón desencadenará el método modTexto() mediante el evento click de


HTML, cuando lo pulsemos.

② El elemento h3 mostrará el valor de la propiedad texto.

Página 60
Ahora, en el componente, archivo ejeventbinding.component.ts, añadimos el
siguiente código dentro de la clase:

src/app/ejeventbinding/ejeventbinding.component.ts


texto = 'Originalmente el texto se carga así';

modTexto() {
this.texto = 'Al pulsar el botón el texto se muestra así';
}

ngOnInit() {
}

Y en el componente raíz, añadimos la etiqueta del componente de la siguiente


forma:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de Event Binding</h3>
<hr>
<app-ejeventbinding></app-ejeventbinding>
</div>

Si comprobamos la aplicación en el navegador, veremos cómo al pulsar en el


botón se modifica el texto.

Página 61
4.4 Two Way Binding

Para finalizar, disponemos de los enlaces two way binding, que enlazan en
ambos sentidos y simultáneamente, los datos de la vista a la fuente de datos y
viceversa.

Este enlace emplea una mezcla entre la sintaxis de eventos y la de interpolación


conocida como banana in a box, y enlaza el valor del elemento HTML de la vista
con la propiedad del componente, de la siguiente manera.

[( directiva )] = “nombredelapropiedad”

Vamos a crear el último ejemplo de esta serie. Para ello, tecleamos desde la
consola del equipo en el directorio raíz de la aplicación:

ng g c ej2waybinding –spec false

En la template, archivo ej2waybinding.component.hmtl, vamos a crear un


campo input y un texto con el siguiente código:

src/app/ej2waybinding/ej2waybinding.component.html

<label>Introduce un valor</label>
<input type="text" class="form-control" [(ngModel)]="texto">
<h3>{{texto}}</h3>

En este caso hemos utilizado la directiva ngModel que más adelante


detallaremos en el apartado correspondiente.

En caso de que no funcione la directiva ngModel, puede ser que la versión de


Angular CLI no haya implementado FormsModule. En ese caso añadimos en el
archivo app.module.ts la importación:

import { FormsModule } from '@angular/forms';

y en el Array de los imports:

FormsModule

Página 62
A continuación, en la clase del archivo ej2waybinding.component.ts añadimos
simplemente la declaración de la variable, con un valor de ejemplo.

src/app/ej2waybinding/ej2waybinding.component.ts


texto = 'Texto original al cargar';

constructor() { }

ngOnInit() {
}

Una vez más, incorporamos la etiqueta del componente al archivo componente


raíz, app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de Two Way Binding</h3>
<hr>
<app-ej2waybinding></app- ej2waybinding>
</div>

Y al refrescar la aplicación, comprobamos como el input y el elemento h3, cargan


en primer lugar el valor de la propiedad texto proveniente del componente,
pero cuando escribamos algo en el input se actualiza de manera
automáticamente en el h3.

Página 63
5 Directivas

Las directivas son clases Angular con instrucciones para crear, formatear e
interaccionar con los elementos HTML en el DOM, y son una de las principales
características de este framework.

Se declaran mediante el empleo del decorador @Directive, y Angular incluye un


gran número de ellas para la mayor parte de las funcionalidades que se
necesitan en una aplicación.

Existen tres tipos de directivas.

• Componentes. Se trata de la aplicación en Angular de la tecnología web


component y ya conocemos uno de sus empleos, las etiquetas HTML de
cada componente que renderizan su plantilla donde las ubiquemos. Se
podría decir que el decorador @Component es una aplicación de las
directivas.

• De atributos. Son directivas que modifican el comportamiento de un


elemento HTML de la misma manera que un atributo HTML, es decir, sin
modificar el layout o presentación del elemento en el DOM. Se identifican
por tener el prefijo ng.

• Estructurales. Estas directivas alteran el layout del elemento en el que se


asocian, añadiendo, eliminando o reemplazando elementos en el DOM.
Se identifican sobre las directivas de atributo por ir precedidas del
símbolo asterisco (*).

Página 64
5.1 Directiva ngIf

ngIf es una directiva estructural de Angular para implementar estructuras if en


nuestra aplicación.

Con esta directiva condicionamos que un elemento html se muestre o no en


función de que se cumpla la expresión que define, normalmente una propiedad
o método. Su sintaxis básica es.

*ngIf=”expresión/propiedad/metodo”

Vamos a crear un ejemplo para conocer su implementación. Creamos un nuevo


componente denominado ejdirectivangif, en la consola del equipo:

ng g c ejdirectivangif --spec false

En el archivo plantilla, ejdirecivangif.component.html escribimos el siguiente


código:

src/app/ejdirecivangif/ejdirecivangif.component.html

<div class="container">
<label>Nombre y Apellidos</label>
<input type="text"
class="form-control" ①
[(ngModel)]="nombre"
placeholder="Complete su nombre y apellidos">
<button type="submit" class="btn btn-primary" ②
*ngIf="nombre">Enviar</button>
</div>

En el cual:

① Creamos un input con la directiva ngModel asociada a la propiedad nombre.

② Y creamos un botón que asociada la directiva ngIf a la propiedad nombre.

Página 65
En la clase del componente en el archivo ejdirectivangif.component.ts
simplemente declaramos la propiedad nombre:

src/app/ejdirecivangif/ejdirecivangif.component.ts

nombre: string;

Y en el archivo app.component.html del componente raíz sustituimos todo el


código por el siguiente:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngIf</h3>
<hr>
<app-ejdirectivangif></app-ejdirectivangif>
</div>

Al refrescar nuestro navegador mostrará el campo sin que aparezca el botón de


enviar, pero cuando comencemos a escribir, comprobamos como se mostrará el
botón ya que la directiva localiza la existencia de la propiedad asociada.

La directiva *ngIf se completa con el uso de else para resolver qué ocurre cuando
no se cumpla la condición. Para ello se añade la etiqueta ng-template, con el
contenido que necesitemos y se asocia una id de esa etiqueta a la palabra
reservada else en la misma expresión de *ngIf.

Página 66
Vamos a comprobarlo con nuestro ejemplo. Sustituimos todo el código de
nuestro archivo ejdirecivangif.component.html por el siguiente:

src/app/ejdirecivangif/ejdirecivangif.component.html

<label>Nombre y Apellidos</label>
<input type="text" class="form-control" [(ngModel)]="nombre"
placeholder="Complete su nombre y apellidos">
<button type="submit" class="btn btn-primary" *ngIf="nombre; else
desactivado">Enviar</button> ①
<ng-template #desactivado> ②
<button type="submit"
class="btn btn-primary"
disabled>Enviar</button>
</ng-template>

En el cual:

① Añadimos a la directiva *ngIf la palabra else en la expresión y la id de la


etiqueta ng-template.

② Y en la etiqueta ng-template introducimos el contenido que se mostrará si


no se cumple la condición declarada por *ngIf.

De esta manera, antes de comenzar a escribir en el input, se muestra el botón


desactivado, ya que le hemos añadido el atributo disabled.

Pero comenzar a escribir, *ngIf reconoce la propiedad y muestra el botón


original sin desactivar.

Página 67
La directiva *ngIf también permite el empleo de métodos para realizar
funcionalidades con una lógica definida en el componente.

Por ejemplo, vamos a sustituir el código de ejdirecivangif.component.html por


el siguiente:

src/app/ejdirecivangif/ejdirecivangif.component.html

<h3>¿Cuál es la capital de España?</h3> ①


<input type="text" class="form-control" [(ngModel)]="capital"> ②
<p *ngIf="!capital; else correcto">Complete la pregunta</p> ③
<ng-template #correcto>
<h4 *ngIf="setResultado(); else incorrecto">¡Correcto!</h4>
</ng-template>
<ng-template #incorrecto>
<h4>Lo siento, inténtelo de nuevo</h4>
</ng-template>

En en el cual:

① Realizamos una pregunta.

② Insertamos un input para responder.

③ Establecemos un primer texto que se mostrara si *ngIf no encuentra la


propiedad capital. Si encuentra la propiedad capital el primer else nos remite a
la etiqueta con id correcto en la que de encadenamos otro *ngIf que utiliza el
método setResultado() y si este método devuelve false, el siguiente else nos
remite a la etiqueta con id incorrecto.

Ahora en el archivo ejdirecivangif.component.ts remplazamos el siguiente


código en la clase:

Página 68
src/app/ejdirecivangif/ejdirecivangif.component.ts

capital: string; ①

constructor() {
}

ngOnInit() {
}

setResultado(){
return this.capital === "Madrid" ? true : false; ②
}

En el cual:

① Declaramos la propiedad capital.

② Y creamos el método setResultado(), que nos devuelve true si capital es


(exactamente) igual a Madrid y false en caso contrario. Este método es el que
se emplea en el segundo *ngIf en la plantilla.

Comprobamos el funcionamiento en el navegador:

Página 69
5.2 Directiva ngStyle

La directiva ngStyle, es una directiva de atributo para establecer de manera


dinámica los estilos de un determinado elemento html en función de la
expresión asociada, normalmente un método. Al ser de atributo, funciona como
estos en las etiquetas html y no alteran el layout del DOM.

Su sintaxis es básicamente:

[ngStyle]=”{ expresión/propiedad/método }”

De nuevo creamos un ejemplo, completando en la consola del equipo en el


directorio raíz del proyecto:

ng g c ejdirectivangstyle --spec false

Comenzamos por incluir el siguiente código html en la plantilla


ejdirectivangstyle.component.html:

src/app/ejdirectivangstyle/ejdirectivangstyle.component.html

<h4>Introduzca la puntuación del Alumno</h4>


<input type="number" class="form-control" [(ngModel)]="puntuacion">①
<hr>
<h4 style="display: inline-block;">Puntuación obtenida:&nbsp; </h4>
<h4 style="display: inline-block;" ②
[ngStyle]="{color:setColor()}">{{puntuacion}}</h4>

En el cual:

① Creamos un input para introducir una puntación.

② Y a continuación mostramos una línea que, con la directiva ngStyle, mostrará


la propiedad puntuación con un estilo de color de la fuente en función del valor
del método setColor().

Página 70
Ahora en la clase del componente en el archivo ejdirectivangstyle.component.ts
añadimos:

src/app/ejdirectivangstyle/ejdirectivangstyle.component.ts

puntuacion: number;

constructor() {
}

ngOnInit() {
}

setColor() {
return this.puntuacion >= 5 ? 'green' : 'red'; ①
}


En el cual además de declarar la propiedad puntuación de tipo número,
añadimos ① el método setColor().

Este método, devolverá ‘green’ si el valor de puntuación es mayor o igual a 5 o


‘red’ en caso contrario. Ambos valores son válidos para la propiedad color de
CSS, que es la definida en la expresión de [ngStyle].

Finalmente y para comprobar, sustituimos el código de la plantilla del


componente raíz app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngStyle</h3>
<hr>
<app-ejdirectivangstyle></app-ejdirectivangstyle>
</div>

Página 71
De esta manera, ahora se mostrará en el navegador:

Página 72
5.3 Directiva ngClass

ngClass es una directiva similar a ngStyle para establecer de manera dinámica


las clases de un elemento HTML.

Veamos un ejemplo. Vamos a crear el componente ejdirectivangclass en la


consola del equipo en el directorio del proyecto con:

ng g c ejdirectivangclass --spec false

En el archivo ejdirectivangclass.component.html de la plantilla añadimos:

src/app/ejdirectivangclass/ejdirectivangclass.component.html

<h4>Introduzca la puntuación del Alumno</h4>


<input type="text" class="form-control" [(ngModel)]="puntuacion">
<hr>
<div *ngIf="puntuacion"> ①

<h4 *ngIf="puntuacion >= 0 && puntuacion <= 10; else aviso" ②


[ngClass]="{ aprobado: puntuacion >= 5,
suspenso: puntuacion <5 }">
Puntuación obtenida: {{ puntuacion }}</h4>
<ng-template #aviso> ③
<h4 *ngIf="puntuacion > 10" class="advertencia">
Introduzca una puntuación menor a 10</h4>
<h4 *ngIf="puntuacion < 0" class="advertencia">
Introduzca una puntuación mayor o igual a 0</h4>
</ng-template>

El código incorpora de nuevo un campo input para introducir una puntuación, y


posteriormente:

① Se crea un div con la directiva ngIf para que se muestre en el momento que
se introduzca una puntuación.

② Se establece un div con ngIf-else para que se muestre si la puntuación está


entre cero y diez, estableciendo la clase CSS aprobado si es mayor o igual a
cinco o la clase CSS suspenso si es menor que cinco.

Página 73
③ En caso de que la puntuación no estuviera en el rango anterior, el ng-
template proporciona dos opciones, si estuviera por encima de diez, avisa para
introducir un valor menor y si estuviera por debajo de cero, avisa para introducir
un valor mayor, siendo la clase CSS en ambos casos, advertencia.

Como hemos añadido clases CSS en la plantilla, las añadimos en nuestro archivo
ejdirectivangclass.component.css de la siguiente manera:

src/app/ejdirectivangclass/ejdirectivangclass.component.css

.advertencia {
color: white;
background-color: orange;
padding: 10px;
}
.aprobado {
color: white;
background-color: green;
padding: 10px;
}

.suspenso {
color: white;
background-color: red;
padding: 10px;
}

Para concluir añadimos la propiedad a la clase del componente en


ejdirectivangclass.component.ts:

src/app/ejdirectivangclass/ejdirectivangclass.component.ts

puntuacion: number;

Página 74
Y la etiqueta del componente en app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngClass</h3>
<hr>
<app-ejdirectivangclass></app-ejdirectivangclass>
</div>

Ahora podemos comprobar en el navegador, las cuatro posibilidades


programadas:

Página 75
5.4 Directiva ngFor

Una de las directivas más empleadas en las aplicaciones Angular es la ngFor,


dedicada a realizar iteraciones y presentar listados por pantalla. Se trata de una
directiva de tipo estructural y su sintaxis es:

*ngFor=”let objeto/propiedad of objetos/propiedades”

En esta sintaxis, se crea dentro del elemento html una variable local con let que
recorrerá el array definido por of y proveniente del componente. Como buena
práctica, el nombre de la variable local será singular y el del array plural.

Vamos a crear un ejemplo muy sencillo para esta directiva. Creamos el


componente en el directorio del proyecto en la consola del equipo:

ng g c ejdirectivangfor -spec

En la clase del componente, dentro del archivo ejdirectivangfor.component.ts


declaramos un simple array de cursos:

src/app/ejdirectivangfor/ejdirectivangfor.component.ts

cursos: string[];

constructor() {
this.cursos = ['Angular', 'HTML', 'CSS'];
}

ngOnInit() {
}

Página 76
Y en la plantilla, ejdirectivangfor.component.html, implementamos la directiva
de la siguiente manera.

src/app/ejdirectivangfor/ejdirectivangfor.component.html

<h3>Cursos Disponibles</h3>
<ul>
① <li *ngFor="let curso of cursos"> ②<h4>{{curso}}</h4></li>
</ul>

En la cual:

① En una lista desordenada incluimos en el item la directiva ngFor para que


itere el array cursos y cada iteración la almacene en la variable local.

② Dentro del ítem introducimos el valor de curso con la sintaxis de


interpolación.

De esta manera, se generarán tantos elementos li como elementos tenga el


array.

Sustituimos la etiqueta de app.component.html por la de este nuevo


componente:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngFor</h3>
<hr>
<app-ejdirectivangfor></app-ejdirectivangfor>
</div>

Y ya podemos comprobar en el navegador como se muestra el listado:

Página 77
Otra de las formas habituales de empleo de la directiva ngFor es iterar un array
de objetos JSON, la forma estandarizada de objetos JavaScript que utilizan las
bases de datos NoSQL basadas en JavaScript.

La sintaxis para declarar un array de objetos JSON es:

nombredelarray: Array<nombredelaclase>;

Veamos otro ejemplo, con lo cual vamos a crear un nuevo componente,


completando en la terminal en el directorio del proyecto:

ng g c arrayobjetos

En primer lugar, dentro del archivo arrayobjetos.component.ts, importamos la


clase Alumno, que recordamos habíamos creamos en el archivo
alumno.modelo.ts:

src/app/arrayobjetos/arrayobjetos.component.ts


import { Alumno } from 'app/modelos/alumno.model';

A continuación en la clase del componente, declaramos el array de objetos y lo


inicializamos con varios objetos de la clase Alumno:


public alumnos: Array<Alumno> = [
{id: 1 , nombre: 'Juan', apellidos: 'Gutierrez', ciudad: 'Madrid'},
{id: 2 , nombre: 'Pedro', apellidos: 'Lopez', ciudad: 'Sevilla'}
];

Página 78
Ahora, en la plantilla del componente, en el archivo
arrayobjetos.component.html añadimos el código html de una tabla en la que
iteramos en sus filas el array alumnos con la directiva ngFor:

src/app/arrayobjetos/arrayobjetos.component.html

<table class="table table-bordered table-striped tabla">


<thead>
<tr class="filters">
<th>id</th>
<th>Nombre</th>
<th>Apellidos</th>
<th>Ciudad</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let alumno of alumnos">
<td>{{ alumno.id }}</td>
<td>{{ alumno.nombre }}</td>
<td>{{ alumno.apellidos }}</td>
<td>{{ alumno.ciudad }}</td>
</tr>
</tbody>
</table>

Nos queda finalmente añadir la etiqueta en la plantilla del componente raíz


app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngFor con objetos</h3>
<hr>
<app-arrayobjetos></app-arrayobjetos>
</div>

Página 79
Y comprobamos en el navegador:

Página 80
5.5 Directiva NgSwitch

NgSwitch es otra de las directivas ampliamente utilizadas a la hora de crear


aplicaciones angular.

Vamos a ver un ejemplo, para lo cual como venimos haciendo, vamos a crear un
nuevo componente en la consola del equipo en la raíz del proyecto:

ng g c ejdirectivangswitch

En primer lugar vamos a crear un array de objetos simples (sin modelo) con
formato de documentos JSON en la clase del componente. Para ello, en el
archivo ejdirectivangswitch.component.ts incoporamos en la clase:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.ts

jugadores: any[] = [
{ nombre: 'Earvin Jhonson', equipo: 'L.A. Lakers'},
{ nombre: 'Larry Bird', equipo: 'Boston Celtics'},
{ nombre: 'Michael Jordan', equipo: 'Chicago Bulls'}
]

Ahora vamos a crear con la directiva ngFor un listado de los jugadores en el


template, por tanto, sustituimos el código del archivo
ejdirectivangswitch.component.html por:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.html

<ul *ngFor="let jugador of jugadores">


<li>
<h4>{{ jugador.nombre }} | {{ jugador.equipo }}</h4>
</li>
</ul>

Página 81
Y sustituimos la etiqueta en el archivo app.component.html por la de este
componente:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngSwitch</h3>
<hr>
<app-ejdirectivangswitch></app-ejdirectivangswitch></div>

Comprobamos en el navegador el listado:

Hasta ahora todo el código responde al ejemplo que vimos en el apartado


anterior, por lo que es el momento de mejorarlo con el uso de NgSwitch.

Para ello sustituimos el código de la template en


ejdirectivangswitch.component.html:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.ts

<div class="text-center">
<ul *ngFor="let jugador of jugadores" [ngSwitch]="jugador.equipo"> ①
<li *ngSwitchCase="'L.A. Lakers'"
class="lakers"><h3>{{jugador.nombre}}</h3><h3 class="equipo"> {{ ②
jugador.equipo}} </h3></li>
<li *ngSwitchCase="'Boston Celtics'"
class="celtics"><h3>{{jugador.nombre}}</h3><h3 class="equipo"> {{
jugador.equipo}} </h3></li>
<li *ngSwitchCase="'Chicago Bulls'"
class="bulls"><h3>{{jugador.nombre}}</h3><h3 class="equipo"> {{
jugador.equipo}} </h3></li>
</ul>
</div>

Página 82
En el cual:

① En la etiqueta ul hemos añadido la directiva ngSwitch entre corchetes y la


asociamos a la propiedad equipo del objeto.

② Creamos tres etiquetas li, una por cada valor individual de la propiedad
equipo, y en cada una de ellas igualamos ngSwitchCase con cada uno de los
valores, para finalmente y también en cada li incorporar una clase css que se
activará en función del valor de la propiedad equipo.

Nos queda añadir las clases CSS, para lo cual incorporamos al archivo
ejdirectivangswitch.component.css el siguiente código CSS:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.css

ul {
text-align: center;
list-style: none;
}

.lakers {
max-width: 600px;
height: 120px;
background-image: url("../../assets/LALakers.png");
background-position-x: 10px;
background-position-y: 10px;
background-repeat: no-repeat;
border-style: solid;
border-width: 5px;
border-color: #552582;
margin-top: 30px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);

.celtics {
max-width: 600px;
height: 120px;
background-image: url("../../assets/BostonCeltics.png");
background-position-x: 10px;
background-position-y: 10px;

Página 83
background-repeat: no-repeat;
border-style: solid;
border-width: 5px;
border-color: #008348;
margin-top: 30px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}

.bulls {
max-width: 600px;
height: 120px;
background-image: url("../../assets/ChicagoBulls.png");
background-position-x: 10px;
background-position-y: 10px;
background-repeat: no-repeat;
border-style: solid;
border-width: 5px;
border-color: #CE1141;
margin-top: 30px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}

.equipo {
color: #707070;
}

Como hemos añadido unas imágenes de logo a las clases CSS, las tenemos que
ubicar en el directorio assets:

Puedes copiar las imágenes de los archivos de este apartado o bien crear el
ejemplo con tus equipos y deporte favorito.

Página 84
Ahora nos vamos al navegador y comprobamos como cada jugador tiene los
colores de su equipo y que ngSwitch establece la clase CSS en función de valor
de la propiedad equipo de cada objeto.

Si además, ahora añadimos el siguiente objeto al array en la clase:

{ nombre: 'Kareem Abdul-Jabbar ', equipo: 'L.A. Lakers'}

Podremos comprobar en el navegador como se añade con los colores y logo de


su equipo.

Página 85
5.6 Creación de directivas propias

Además de las directivas proporcionadas por Angular, el framework permite la


creación de nuevas directivas para nuestras funcionalidades.

Podemos crear el archivo de manera manual e incorporarlo a la aplicación con


sus correspondiente importaciones o bien, de una manera más sencilla, utilizar
la herramienta Angular CLI.

Para ello, en el directorio raíz del proyecto, completamos en la consola del


equipo por ejemplo:

ng generate directive menuitem

De esta manera, Angular CLI, crea un archivo menuitem.directive.ts con el


siguiente código:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.ts

import { Directive } from '@angular/core'; ①

@Directive({
selector: '[appMenuitem]' ②
})
export class MenuitemDirective { ③
constructor() { }
}

En el cual se importa ① la clase Directive de Angular, se implementa ② el


decorador @Directive con el metadato selector que determinará el nombre de
nuestra directiva, y ③ se exporta una clase donde se define la lógica que
realizará la directiva.

Dentro de la clase podemos escribir cualquier código de acuerdo a las


necesidades de nuestra aplicación, y podemos ayudarnos para ello de una
serie de decoradores que proporciona Angular.

Página 86
En nuestro ejemplo, vamos a usar los decoradores HostListener, HostBinding
con lo cual en primer lugar sustituimos la importación por la siguiente:

src/app/ejdirectivangswitch/ejdirectivangswitch.component.ts

import { Directive, HostListener, HostBinding } from '@angular/core';

Y a continuación sustituimos el código de la clase por el siguiente:

@HostBinding ('class.itemOrange') private mostrar: boolean = false; ①

@HostListener('mouseover') onOver() { ②
this.mostrar = true;
}
@HostListener('mouseout') onOut() { ③
this.mostrar = false;
}

En el cual :

① Utilizamos el decorador HostBinding para enlazar la clase CSS itemOrange


con una propiedad booleana que denominamos mostrar, inicializada como
false.

② Utilizamos el decorador HostListener para que cuando se realice un evento


mouseover (aproximar el ratón) se ejecute el método onOver que cambia el
valor de la propiedad mostrar a true.

③ Y de nuevo usamos el decorador HostListener para que con un evento


mouseout (quitar el ratón) ejecute el método onOut que cambiará la propiedad
mostrar a su estado original, false.

En resumen, estamos realizando una directiva que permitirá aplicar una clase
CSS cuando se aproxime el ratón al elemento HTML donde se implemente.

Nuestra nueva directiva estará lista para usar, ya que además de crearla, Angular
CLI modifica el archivo app.module.ts para que esté disponible en toda la
aplicación.

Página 87
Lo comprobamos accediendo al archivo:

src/app/app.module.ts


import { MenuitemDirective } from './menuitem.directive';

MenuitemDirective
]

Como en nuestro ejemplo de directiva, vamos a implementar una clase CSS, la


creamos en el archivo de estilos generales styles.css que se encuentra en el
directorio app:

src/app/styles.css

.item-orange {
border-left-style: solid;
border-width: 5px;
border-left-color: orange;
padding-left: 10px;
}

Y ahora ya podemos implementar esta clase a través de nuestra directiva con


la funcionalidad de activación con el ratón.

Para comprobarlo, creamos un nuevo componente denominado ejmidirectiva


en la consola del equipo:

ng g c ejmidirectiva –spec false

Y en el archivo ejmidirectiva.component.html de la template, vamos a poner


un listado de elementos html a los que añadimos nuestra directiva con el
nombre que definimos en su selector:

Página 88
src/app/ejmidirectiva/ejmidirectiva.component.html

<div class="container">
<h1 appMenuitem>Título</h1>
<h1 appMenuitem>Descripción</h1>
<h1 appMenuitem>Precio</h1>
</div>

Implementamos la etiqueta de este componente en el archivo raíz


app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de directiva ngFor con objetos</h3>
<hr>
<app-ejmidirectiva></app-ejmidirectiva>
</div>

Y comprobamos finalmente en el navegador, el funcionamiento de la directiva:

Como la directiva se puede emplear en cualquier parte de la aplicación, es una


buena fórmula para reutilizar el código, y como hemos visto, su desarrollo no es
demasiado complicado.

Página 89
5.7 Utilización de @Input entre componentes

Angular permite compartir a través del decorador @Input, propiedades y valores


entre componentes anidados.

Vamos a ver con un ejemplo como se incorpora este decorador. En primer lugar
creamos un componente padre desde la consola en el directorio raíz del
proyecto con:

ng g c padre --spec false

Y otro componente hijo:

ng g c hijo --spec false

Nos vamos a la plantilla del componente padre.component.html y escribimos el


siguiente código:

src/app/padre/padre.component.html

<h2>Componente Padre</h2>
<div style=" border-style: solid; border-width: 2px; border-color: orange;
padding: 10px">
</div>

E incluimos su etiqueta en la plantilla del componente raíz app.component.html:

src/app/app.component.html

<div class="container" >


<h3>Ejemplo de uso de @Input</h3>
<hr>
<app-padre></app-padre>
</div>

Página 90
Comprobamos en el navegador su correcto funcionamiento:

Ahora vamos a la clase del componente hijo en el archivo hijo.component.ts y


creamos la propiedad aviso con un string de ejemplo:

src/app/hijo/hijo.component.ts

public aviso: string = 'Este texto proviene del componente hijo';

Completamos un sencillo código en el archivo hijo.component.html para


mostrar el valor de la propiedad aviso:

src/app/hijo/hijo.component.html

<h4>{{aviso}}</h4>

Y a continuación, vamos a modificar la plantilla del componente padre en el


archivo padre.component.html para incluir la etiqueta del componente hijo:

src/app/padre/padre.component.html

<h2>Componente Padre</h2>
<div style=" border-style: solid; border-width: 2px; border-color: orange;
padding: 10px">
<app-hijo></app-hijo>
</div>

Página 91
Comprobamos finalmente en el navegador:

Hasta ahora hemos empleado las técnicas de Angular sin mayor novedad, pero
podemos incluir valores en las propiedades del hijo a través del padre, es decir
compartir las propiedades entre dos componentes.

Para ello emplearemos el decorador Input de la siguiente manera. En primer


lugar modificamos el archivo hijo.component.ts para que la propiedad aviso
pueda ser compartida.

src/app/hijo/hijo.component.ts

import { Component, OnInit, Input } from '@angular/core'; ①

@Component({
selector: 'app-hijo',
templateUrl: './hijo.component.html',
styleUrls: ['./hijo.component.css']
})
export class HijoComponent implements OnInit {

@Input() aviso: string; ②

constructor() { }

ngOnInit() {
}

Página 92
En el cual:

① Importamos la clase Input del core de Angular,

② Y aplicamos el decorador @Input() a la propiedad aviso, sin inicializarla.

Ahora en el componente padre, en el archivo padre.component.ts creamos una


nueva propiedad con un valor:

src/app/padre/padre.component.ts

valorPadre: string = 'Este texto se inyecta desde el padre';

Y podemos usar la propiedad del hijo para usarla en su plantilla con un valor
proveniente del padre. Para ello en el archivo padre.component.html
modificamos la etiqueta del hijo para añadir esta sintaxis:

src/app/padre/padre.component.html

<app-hijo [aviso]="valorPadre"></app-hijo>

Si ahora regresamos al navegador, podemos comprobar como en la plantilla del


componente hijo y la propiedad aviso, hemos inyectado el valor de una
propiedad, valorPadre, del componente padre.

Página 93
Incluso podemos hacerlo más complejo introduciendo un array de valores desde
el padre a la plantilla del hijo. Por ejemplo, en el archivo del componente
padre.component.ts, cambiamos la propiedad por este array:

src/app/padre/padre.component.ts

avisos: string[] = ['Aviso 1' , 'Aviso 2' , 'Aviso 3'];

Y ahora en la plantilla en el archivo padre.component.html hacemos uso de


ngFor para iterar avisos e introducirlos en la propiedad aviso del component hijo
de la siguiente forma:

src/app/padre/padre.component.html

<app-hijo *ngFor="let avisop of avisos" [aviso]="avisop"></app-hijo>

Con lo cual en el navegador se mostrará:

Página 94
5.8 Utilización de @Output entre componentes

Otro de los decoradores a emplear en Angular entre componentes es Output.


Volvamos al ejemplo del apartado anterior y antes de utilizar Output vamos a
crear un método para marcar los avisos leídos.

Para ello en el componente hijo, modificamos el archivo hijo.component.html


sustituyendo el código por el siguiente:

src/app/hijo/hijo.component.html

<div style=" border-style: solid; border-width: 2px; border-color: blue;


padding: 20px; margin: 10px">
<h4 [ngClass]="{tachado: leido == true}" style="display: ①
inline">{{aviso}}</h4>
<button *ngIf="leido == false" class="btn btn-success float-md-right"
(click)="marcar()">Marcar como Leído</button>
<button *ngIf="leido == true" class="btn btn-danger float-md-right" ②
(click)="marcar()">Desmarcar como Leído</button>
</div>

En el cual:

① Añadimos al aviso una directiva ngClass para que aplique la clase tachado si
el valor de leído es true.

② Y añadimos dos botones que se mostrarán o no en función de que la


propiedad leido sea verdadera o falsa, con un evento clic que desencadena el
método marcar() para que modifique el valor de esa propiedad.

Página 95
A continuación vamos a crear la propiedad leido y el método marcar en el
archivo hijo.component.ts:

src/app/hijo/hijo.component.ts


@Input() aviso: string;

leido: boolean = false;

marcar(event) {
this.leido = !this.leido;
}

Y nos queda añadir la clase tachado en el archivo hijo.component.css:

src/app/hijo/hijo.component.css

.tachado {
text-decoration:line-through;
}

Ahora podemos en el navegador como al pulsar en cada botón, el aviso se


marca y desmarca como tachado:

Página 96
Pues bien, la funcionalidad Output permite desencadenar un método del
componente padre a partir de un método del componente hijo y pasar datos
como parámetros.

En primer lugar vamos a modificar el código del componente hijo en su archivo


hijo.component.ts, sustituimos la primera línea de importación por:

src/app/hijo/hijo.component.ts


import { Component, OnInit, Input, Output, EventEmitter } from
'@angular/core';

Añadimos el decorador @Output en la clase creando el método


mensajeMarcado:


@Output() mensajeMarcado = new EventEmitter();

Para finalizar en este archivo, creamos en la clase un nuevo método detectar:


detectar(event) {
this.mensaje = this.aviso;
this.mensajeMarcado.emit(this.mensaje);
}

Que detectará qué aviso se ha marcado y los emite como parámetro mensaje
del método mensajeMarcado.

Página 97
A continuación en la template del componente hijo, hijo.component.html,
añadimos al botón de marcado de aviso y el método detectar, sustituyendo el
código del botón por el siguiente:

src/app/hijo/hijo.component.html


<button *ngIf="leido == false" class="btn btn-success pull-right"
(click)="marcar() ; detectar($event)">Marcar como Leído</button>

Pasamos al componente padre ahora. En su plantilla del archivo


padre.component.html modificamos el código de la etiqueta del componente
hijo para añadir el método que hemos emitido a través de @Output de la
siguiente forma:

src/app/padre/padre.component.html


<app-hijo *ngFor="let avisop of avisos" [aviso]="avisop"
(mensajeMarcado)="mostrarMensaje($event)"></app-hijo>

En el que vemos como el método del componente hijo se asocia al método


mostrarMensaje.

En este archivo padre.component.html, también añadimos una línea para


mostrar un mensaje antes del cierre del div:


<h3 style="text-align:center"> {{ texto }}</h3>
</div>

Página 98
Por último nos queda modificar el componente padre en el archivo
padre.component.ts. En primer lugar creamos la propiedad texto que se
mostrará en el mensaje añadiendo:

src/app/padre/padre.component.html


texto: string;

Y a continuación añadimos el método mostrarMensaje que recibe el parámetro


mensaje del componente hijo a través del método mensajeMarcado:

mostrarMensaje(event) {
this.texto = event + ' marcado como leido';
}

Finalizado el código, podemos comprobar en el navegador como al marcar


cualquier aviso, se muestra el mensaje con el aviso ‘marcado como leído’ gracias
al enlace de métodos mediante Output entre diferentes componentes.

Página 99
Anexo Extra I Instalación de Node y NPM

Para instalar Node y NPM en nuestro equipo, accedemos a la web de Node JS


en la url:

https://nodejs.org/es/

Directamente en la web pulsamos en Descargar para Windows (la web detectará


nuestro sistema operativo si empleamos otro) para descargar el paquete LTS de
instalación:

Una vez descargado el archivo .msi lo ejecutamos con doble clic desde nuestra
carpeta de descargas para iniciar el asistente:
Realizamos los pasos que nos vaya solicitando el asistente por defecto, y si nos
fijamos, el asistente instalará tanto Node Js como NPM, y añadirá sus rutas al
path de windows:

Una vez concluida la instalación es necesario reiniciar el equipo para que las
rutas se carguen y podamos emplear node o nmp desde la consola.

Una vez que se reinicie el equipo, comprobamos la correcta instalación


tecleando en la consola:

node –v

npm –v

Para obtener las versiones y la certeza de que ambos están instalados.


En el caso de instalar Node y NPM en un equipo Mac el proceso es exactamente
igual, siendo la última pantalla del asistente la siguiente:

En el cual se nos especifica donde han sido instalados Node JS y NPM y como
debemos tener establecido en el path la ruta /usr/local/bin/
Anexo Extra II de Visual Studio Code

Exiten multitud de editores de código e IDES para desarrollar aplicaciones en


Angular.

Nuestro editor favorito es Visual Studio Code, que además distribuye libremente
Microsoft.

Para instalarlo accedemos a la url:

https://code.visualstudio.com/

Y directamente pulsamos en Download for Windows (la web detectará nuestro


sistema operativo si empleamos otro):
Una vez descargado el paquete, lo ejecutamos y realizamos los pasos que nos
vaya solicitando:

Reiniciamos el equipo y dispondremos de Visual Studio Code. La mayoría de


funcionalidades interesantes de Visual Studio Code, se implementan a través de
plugins.

Para instalar un plugin, pulsamos en el último botón del menú lateral izquierdo
y en el buscador, completamos el nombre de un plugin, por ejemplo HTML
Snippets y pulsamos en el botón verde Instalar:
Para que funcione, en la pantalla de detalle del plugin pulsamos en el botón azul
Recargar y en el cuadro de diálogo pulsamos en Volver a cargar Windows.

Con esto, tendremos el plugin implementado y funcionando.

Para desarrollar en Angular, además de este plugin, son también muy


interesantes los siguientes:

Angular Essentials del desarrollador johnpapa

Autorename Tag del desarrollador Jun Han

Bracket Pair Colorizer del desarrollador CoenraadS

Material Icon Theme del desarrollador Phillip Kief

Path Intellisense del desarrollador Christian Kohler

TSlint del desarrollador egamma

También podría gustarte