0% encontró este documento útil (0 votos)
23 vistas60 páginas

Unidad 4

Este documento presenta un módulo sobre el desarrollo de APIs RESTful con Node.js y aplicaciones de frontend con Angular 5. El módulo comienza explicando conceptos básicos de REST y cómo crear un servidor Node.js y modelos de datos para una API REST. Luego, explica cómo crear una aplicación Angular 5, integrarla con la API REST mediante rutas de Express, y desarrollar componentes en Angular para realizar operaciones CRUD sobre los datos expuestos por la API. Finalmente, detalla cómo probar y validar la aplicación completa.

Cargado por

Mike Velazquez
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)
23 vistas60 páginas

Unidad 4

Este documento presenta un módulo sobre el desarrollo de APIs RESTful con Node.js y aplicaciones de frontend con Angular 5. El módulo comienza explicando conceptos básicos de REST y cómo crear un servidor Node.js y modelos de datos para una API REST. Luego, explica cómo crear una aplicación Angular 5, integrarla con la API REST mediante rutas de Express, y desarrollar componentes en Angular para realizar operaciones CRUD sobre los datos expuestos por la API. Finalmente, detalla cómo probar y validar la aplicación completa.

Cargado por

Mike Velazquez
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/ 60

UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB

Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

UNIVERSIDAD TECNOLÓGICA NACIONAL


FACULTAD REGIONAL CÓRDOBA

Secretaría de Extensión Universitaria

Área de Educación a Distancia

Coordinador General de Educación a Distancia:

Magister Leandro D. Torres

Curso:
DIPLOMATURA EN DESARROLLO WEB EV 15030

Módulo:
“API Rest con NodeJS y SPA con Angular 5”

Autor:
Ing. Mario Di Giorgio

Autor: Ing. Mario Di Giorgio


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Referencias

Este material se confecciono en base a las últimas tendencias que hoy se encuentra en Internet.
Para eso se buscó el mejor material y se recompilo dicha información para facilitar el aprendizaje
del mismo.

El material utilizado para esta primera unidad fue:

 Cómo crear un API REST usando Node.js, Express y MongoDB


 Angular IO (http://angular.io)

Autor: Ing. Mario Di Giorgio 1


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Índice

Capítulo 9 .................................................................................................................................. 5

REST...................................................................................................................................... 5

9.1 Introducción básica ........................................................................................................ 5

9.2 Desarrollando nuestro API RESTful ............................................................................... 5

9.3 Nuestro servidor Node,js................................................................................................ 6

9.4 Creando los modelos de nuestra API REST .................................................................. 7

9.5 Implementando los controladores de nuestras rutas o endpoints ................................. 10

9.5.1 Probando nuestro API REST en el navegador .......................................................13

Capítulo 10 ...............................................................................................................................18

Angular 5 ...............................................................................................................................18

10.1 INTRODUCCION ....................................................................................................... 18

10.2 Requisitos .................................................................................................................. 18

10.2.1 Que es TypeScript ...............................................................................................18

10.2.2. Preparando el ambiente .....................................................................................19

10.3 Creando una nueva aplicación Angular 5 ................................................................... 20

10.4. Reemplace el servidor Web con Express.js .............................................................. 22

10.4.1 Crear servidor usando Express generator ...........................................................22

10.4.2 Crear servidor Express manualmente ..................................................................25

10.4.3 Agregar API Routes .............................................................................................29

10.5 Instalar y configurar Mongoose.js .............................................................................. 30

10.5.1 Crear el modelo de Mongoose.js .........................................................................32

10.6 Crear rutas en Express para acceder a los datos del libro vía API RESTful ............... 33

10.7 Crear componente de Angular 5 para mostrar la lista de libros .................................. 35

10.7.1 Instale Bootstrap y Font-Awesome ......................................................................37

10.7.2 Configurar bootstrap como hoja de estilos en INDEX.HTML................................38

Autor: Ing. Mario Di Giorgio 2


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.7.3 Crear en Angular 5 rutas al componente Book ....................................................39

10.8 Crear componentes de Angular para ABM de libros. ................................................. 41

10.8.1 Componente de Detalles .....................................................................................41

10.8.2 Componente agregar nuevo libro.........................................................................44

10.8.3 Componente editar libro ......................................................................................48

10.8.4 Función de eliminar libro ......................................................................................52

10.9 Ejecute y pruebe la aplicación CRUD de Angular 5 ................................................... 53

10.10 Modificar el componente de creación de libro para usar validadores especiales. ..... 55

10.11 Ejecute y pruebe la aplicación Angular 5 Completa ................................................. 58

Autor: Ing. Mario Di Giorgio 3


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Autor: Ing. Mario Di Giorgio 4


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Capítulo 9
REST
9.1 Introducción básica

REpresentational State Transfer (REST) es un estilo de arquitectura para sistemas hipermedia


distribuidos, tales como la World Wide Web. El centro de la arquitectura RESTful es el concepto
de los recursos identificados por los identificadores de recursos universal (universal resource
identifiers URIs). Estos recursos pueden ser manipulados usando un interfaz estándar, tales
como el HTTP, y la información es intercambiada usando representaciones de estos recursos.

9.2 Desarrollando nuestro API RESTful

El primer paso es crear un directorio en tu entorno local para la aplicación, e iniciar un repositorio
para guardar los cambios y que luego podamos desplegarlo por ejemplo en Heroku. Yo
personalmente uso Git porque es una maravilla de la creación y porque a Heroku es lo que le
mola ;)
C:\ md node-api-rest-example
C:\ cd node-api-rest-example

Antes de empezar, necesitas tener Node instalado en tu computadora, para que funcione en tu
entorno local de desarrollo.

El primer código que necesitamos escribir en una aplicación basada en Node es el archivo
package.json. Éste archivo nos indica que dependencias vamos a utilizar en ella. Este archivo
va en el directorio raíz de la aplicación:

Por lo tanto package.json tendrá:


{
"name": "node-api-rest-example",
"version": "2.0.0",
"dependencies": {
"mongoose": "~3.6.11",
"express": "^4.7.1",
"method-override": "^2.1.2",
"body-parser": "^1.5.1"
}
}

Autor: Ing. Mario Di Giorgio 5


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Y ahora para descargar las dependencias escribimos lo siguiente en la consola y NPM (el gestor
de paquetes de Node) se encargará de instalarlas.
$ npm install

9.3 Nuestro servidor Node,js

Con todo listo, podemos comenzar a codear de verdad. Creamos un fichero llamado app.js en el
directorio raíz que será el que ejecute nuestra aplicación y arranque nuestro server. Crearemos
en primer lugar un sencillo servidor web para comprobar que tenemos todo lo necesario
instalado, y a continuación iremos escribiendo más código.
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
methodOverride = require("method-override");
mongoose = require('mongoose');

app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(methodOverride());

var router = express.Router();

router.get('/', function (req, res) {


res.send("Hello World!");
});

app.use(router);

app.listen(3000, function () {
console.log("Node server running on http://localhost:3000");
});

¿Qué hace este código? Muy sencillo, las primeras líneas se encargan de incluir las
dependencias que vamos a usar, algo así como los includes en C o PHP, o los import de Python.
Importamos Express para facilitarnos crear el servidor y realizar llamadas HTTP. Con http
creamos el servidor que posteriormente escuchará en el puerto 3000 de nuestro ordenador (O el
que nosotros definamos).

Autor: Ing. Mario Di Giorgio 6


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Con bodyParser permitimos que pueda transformar JSON, methodOverride() nos permite
implementar y personalizar métodos HTTP.

Podemos declarar las rutas con app.route (nombre_de_la_ruta) seguido de los verbos .get(),
.post(), etc… y podemos crear una instancia para ellas con express.Router(). En este primer
ejemplo vamos a hacer que sólo reciba una petición GET del navegador y muestre en el mismo
la frase “Hello World”

Para ejecutar este pequeño código sólo tienes que escribir en consola lo siguiente y abrir un
navegador con la URL http://localhost:3000
C:\node_path\node app.js
Node server running on http://localhost:3000

Si todo va bien, esto es lo que se verá:

9.4 Creando los modelos de nuestra API REST

En esta parte vamos a crear un modelo usando Mongoose para poder guardar la información en
la base de datos siguiendo el esquema. Como base de datos vamos a utilizar MongoDB.
MongoDB es una base de datos Open Source NoSQL orientada a documentos tipo JSON, lo
cual nos viene que ni pintado para entregar los datos en este formato en las llamadas a la API.

Para este ejemplo vamos a crear una base de datos de series de TV, por tanto, vamos a crear
un modelo (Archivo: models/tvshow.js) que incluya la información de una serie de TV, como
pueden ser su título, el año de inicio, país de producción, una imagen promocional, número de
temporadas, género y resumen del argumento:
var mongoose = require('mongoose'),
Autor: Ing. Mario Di Giorgio 7
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Schema = mongoose.Schema;

var tvshowSchema = new Schema({


title: {
type: String
},
year: {
type: Number
},
country: {
type: String
},
poster: {
type: String
},
seasons: {
type: Number
},
genre: {
type: String,
enum: ['Drama', 'Fantasy', 'Sci-Fi', 'Thriller', 'Comedy']
},
summary: {
type: String
}
});

module.exports = mongoose.model('TVShow', tvshowSchema);

Con esto ya podemos implementar la conexión a la base de datos en el archivo app.js añadiendo
las siguientes líneas:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tvshows');

Quedando así el código de app.js:


var express = require("express"),
app = express(),
http = require("http"),
server = http.createServer(app),
mongoose = require('mongoose');

app.use(bodyParser.urlencoded({
extended: false

Autor: Ing. Mario Di Giorgio 8


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

}));
app.use(bodyParser.json());
app.use(methodOverride());

var router = express.Router();

router.get('/', function (req, res) {


res.send("Hello World!");
});

app.use(router);

mongoose.connect('mongodb://localhost/tvshows', function (err, res) {


if (err) {
console.log('ERROR: connecting to Database. ' + err);
}
app.listen(3000, function () {
console.log("Node server running on http://localhost:3000");
});
});

Para que esto funcione en nuestro entorno local, necesitamos tener instalado MongoDB.

Para poder iniciar MongoDB debes ejecutar en otra terminal:


C:\mongodb_path\mongod
all output going to: /usr/local/var/log/mongodb/mongo.log

Con Mongo arrancado ya podemos ejecutar la aplicación como en la parte anterior con node
app.js desde la terminal, si todo va bien tendremos algo en la pantalla como esto:
C:\node_path\node app.js
Node server running on http://localhost:3000
Connected to Database

Ahora desde otra terminal, podemos entrar al shell de MongoDB y comprobar que la base de
datos se ha creado correctamente. Para ello ejecutamos el comando mongo
C:\mongodb_path\mongo
MongoDB shell version: 2.4.1
connecting to: test
> use tvshows
switched to db tvshows
> show dbs

Autor: Ing. Mario Di Giorgio 9


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

local 0.078125GB
tvshows (empty)
>_

Ya tenemos todo configurado y listo para albergar los datos, sólo nos queda crear las rutas que
definirán las llamadas a la API para poder guardar y consultar la información.

9.5 Implementando los controladores de nuestras rutas o endpoints

Los controladores de las rutas de nuestro API los vamos a crear en un archivo separad que
llamaremos controllers/tvshows.js. Gracias a exports conseguimos modularizarlo y que pueda
ser llamado desde el archivo principal de la aplicación. El código de a continuación es el comienzo
del archivo con la primera función que será la que devuelva todos los registros almacenados:
//File: controllers/tvshows.js
var mongoose = require('mongoose');
var TVShow = mongoose.model('TVShow');

//GET - Return all tvshows in the DB


exports.findAllTVShows = function (req, res) {
TVShow.find(function (err, tvshows) {
if (err) res.send(500, err.message);

console.log('GET /tvshows')
res.status(200).jsonp(tvshows);
});
};

De esta manera tan sencilla, al llamar a la función findAllTVShows se envía como respuesta toda
la colección de tvshows almacenada y en formato JSON. Si queremos que sólo nos devuelva un
registro con un identificador único, tenemos que crear una función tal que la siguiente:
//GET - Return a TVShow with specified ID
exports.findById = function (req, res) {
TVShow.findById(req.params.id, function (err, tvshow) {
if (err) return res.send(500. err.message);

console.log('GET /tvshow/' + req.params.id);


res.status(200).jsonp(tvshow);
});
};

Autor: Ing. Mario Di Giorgio 10


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Con las funciones find() y findById() podemos buscar en la base de datos a partir de un modelo.
Ahora desarrollaré el resto de funciones que permiten insertar, actualizar y borrar registros de la
base de datos. La función de a continuación sería la correspondiente al método POST y lo que
hace es añadir un nuevo objeto a la base de datos:
//POST - Insert a new TVShow in the DB
exports.addTVShow = function (req, res) {
console.log('POST');
console.log(req.body);

var tvshow = new TVShow({


title: req.body.title,
year: req.body.year,
country: req.body.country,
poster: req.body.poster,
seasons: req.body.seasons,
genre: req.body.genre,
summary: req.body.summary
});

tvshow.save(function (err, tvshow) {


if (err) return res.status(500).send(err.message);
res.status(200).jsonp(tvshow);
});
};

Primero creamos un nuevo objeto tvshow siguiendo el patrón del modelo, recogiendo los valores
del cuerpo de la petición, lo salvamos en la base de datos con el comando save() y por último lo
enviamos en la respuesta de la función.

La siguiente función nos permitirá actualizar un registro a partir de un ID. Primero buscamos en
la base de datos el registro dado el ID, y actualizamos sus campos con los valores que devuelve
el cuerpo de la petición:
//PUT - Update a register already exists
exports.updateTVShow = function (req, res) {
TVShow.findById(req.params.id, function (err, tvshow) {
tvshow.title = req.body.petId;
tvshow.year = req.body.year;
tvshow.country = req.body.country;
tvshow.poster = req.body.poster;
tvshow.seasons = req.body.seasons;
tvshow.genre = req.body.genre;
tvshow.summary = req.body.summary;
Autor: Ing. Mario Di Giorgio 11
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

tvshow.save(function (err) {
if (err) return res.status(500).send(err.message);
res.status(200).jsonp(tvshow);
});
});
};

Y por último para completar la funcionalidad CRUD de nuestra API, necesitamos la función que
nos permita eliminar registros de la base de datos y eso lo podemos hacer con el código de a
continuación:
//DELETE - Delete a TVShow with specified ID
exports.deleteTVShow = function (req, res) {
TVShow.findById(req.params.id, function (err, tvshow) {
tvshow.remove(function (err) {
if (err) return res.status(500).send(err.message);
res.status(200).send();
})
});
};

Como puedes ver, usamos de nuevo el método .findById() para buscar en la base de datos y
para borrarlo usamos .remove() de la misma forma que usamos el .save() para salvar.

Ahora tenemos que unir estas funciones a las peticiones que serán nuestras llamadas al API.
Volvemos a nuestro archivo principal, app.js y declaramos las rutas, siguiendo las pautas de
Express v.4
var TVShowCtrl = require('./controllers/tvshows');

// API routes
var tvshows = express.Router();

tvshows.route('/tvshows')
.get(TVShowCtrl.findAllTVShows)
.post(TVShowCtrl.addTVShow);

tvshows.route('/tvshows/:id')
.get(TVShowCtrl.findById)
.put(TVShowCtrl.updateTVShow)
.delete(TVShowCtrl.deleteTVShow);

app.use('/api', tvshows);

Autor: Ing. Mario Di Giorgio 12


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

9.5.1 Probando nuestro API REST en el navegador

A continuación, voy a probar una herramienta online que nos permite jugar con las llamadas al
API y poder consultar y almacenar datos para probarla y ver su funcionamiento un poco más
claro.

Para ello nos dirigimos a restconsole.com que es una extensión de Google Chrome, que permite
hacer lo que queremos de una manera visual y sencilla.

Antes de probarlo, debemos tener mongo y el servidor node de nuestra app corriendo. Una vez
hecho esto introducimos los siguientes datos para hacer una llamada POST que almacene un
registro en la base de datos.

 Target: http://localhost:3000/tvshow (Dónde está ejecutándose la aplicación y la llamada


al método POST que hemos programado)
 Content-Type: application/json (en los dos inputs que nos dan)
 Request-Payload: Aquí va el cuerpo de nuestra petición, con el objeto JSON siguiente
(por ejemplo):
{
"title": "LOST",
"year": 2004,
"country": "USA",
"poster": "http://ia.media-
imdb.com/images/M/MV5BMjA3NzMyMzU1MV5BMl5BanBnXkFtZTcwNjc1ODUwMg@@._V1_SY317_
CR17,0,214,317_.jpg",
"seasons": 6,
"genre": "Sci-Fi",
"summary": "The survivors of a plane crash are forced to live with each
other on a remote island, a dangerous new world that poses unique threats of
its own."

Autor: Ing. Mario Di Giorgio 13


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Pulsamos SEND y si todo va bien, la petición se realizará y abajo de la aplicación REST Console
veremos algo como esto:

¿Cómo comprobamos si se ha guardado en nuestra base de datos? Muy sencillo, en nuestro


terminal ejecutamos el Shell de mongo con el comando mongod e introducimos los siguientes
comandos:
C: \mongodb_path\ mongo
MongoDB shell version: 2.4 .1
connecting to: test >
show databases
tvshows 0.203125 GB
>
use tvshows
switched to db tvshows
>
show collections
system.indexes
tvshows
>
db.tvshows.find() {
"title": "LOST",

Autor: Ing. Mario Di Giorgio 14


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

"year": 2004,
"country": "USA",
"poster": "http://ia.media-
imdb.com/images/M/MV5BMjA3NzMyMzU1MV5BMl5BanBnXkFtZTcwNjc1ODUwMg@@._V1_SY317_CR17
,0,214,317_.jpg",
"seasons": 6,
"genre": "Sci-Fi",
"summary": "The survivors of a plane crash are forced to live with each
other on a remote island, a dangerous new world that poses unique threats of its
own.",
"_id": ObjectId("51b44d7899ac57fb18000002"),
"__v": 0
}

Y ahí la tenemos, puedes probar a introducir alguna más, para tener mayor contenido con el que
probar. Una vez introduzcas varios registros, puedes probar a llamarlos a través de la petición
GET que hemos preparado: http://localhost:3000/tvshows la cuál te mostrará algo parecido a
esto:

Autor: Ing. Mario Di Giorgio 15


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

También podemos llamar a un sólo registro gracias a la petición GET tvshows/:id que
programamos, si ejecutamos por ejemplo
http://localhost:3000/tvshow/51b44d7899ac57fb18000002 nos devolverá un único objeto:

Los métodos restantes PUT y DELETE funcionan de manera parecida al POST sólo que hay que
pasarte el valor del ID del objeto que queremos actualizar o borrar. Te invito a que lo pruebes en
la Tutorial de NodeJS, creando un API REST - REST Console.

Autor: Ing. Mario Di Giorgio 16


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Con esto tendríamos el funcionamiento básico y programación de lo que sería una API REST.
Como puedes ver es bastante sencillo y utilizas Javascript en todas partes, como lenguaje de
servidor (Node), como formato de datos (JSON) y como base de datos (MongoDB)

Autor: Ing. Mario Di Giorgio 17


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Capítulo 10
Angular 7

10.1 INTRODUCCION

ANGULAR es un framework de desarrollo para JavaScript creado por Google para crear
principalmente “single page application” (SPA), o aplicaciones de página única. Es uno de los
frameworks más populares para desarrollar aplicaciones modernas y escalables en el lado del
cliente.

En este artículo veremos cómo crear rápidamente una aplicación Angular (Angular 2, Angular
4 , Angular 5) utilizando Angular CLI (Command Line Interface) y Angular Material un módulo
que nos permite trabajar con componentes de interfaz de usuario completos y modernos que
funcionan en la web, el móvil y en escritorio basados en Material Design. (Material Design es un
conjunto de especificaciones definidas por Google para mantener una estructura coherente y
atractiva en la web y aplicaciones móviles.)

Las últimas versiones de Angular han mejorado el funcionamiento general del framework y nos
permite utilizar TypeScript para definir nuestras clases, propiedades y métodos, generando un
código mucho más limpio.

Crearemos una aplicación utilizando la versión de Angular 5 (desde cero) para mostrar logros o
historias, crearemos nuestro propio componente, mostraremos datos de variables, listaremos
arreglos y utilizaremos angular material para mejorar la interfaz de usuario.

10.2 Requisitos

Para comenzar, asegúrese de tener instalado NodeJS (v6.9 +) y NPM (v3.x +). en su máquina.

10.2.1 Que es TypeScript

Antes que nada debemos saber que Angular a partir de la versión 2 cambia de paradigma de
programación y se va de la clásica programación funcional a la programación orientada a objetos
para lo que es necesario tener un código que sea fuertemente tipado, algo que JavaScript carece
dado sus características de lenguaje dinámico y flexible, por lo que siempre regulado por los
Autor: Ing. Mario Di Giorgio 18
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

estándares ECMAScript 5 en adelante Microsoft creó un lenguaje de codigo abierto llamado


TypeScript, el mismo se identifica con la extensión .ts en sus archivos y es un JavaScript
enriquecido para parecerme más a los lenguajes orientado a objetos como Java.

Esto se hizo en pos de poder usar codigo de manera mas segura y mejorar la depuración y el
control de errores que con JavaScript puro es muy difícil, casi imposible de mantener.

Lo que queda por saber de TypeScript es que es un lenguaje que luego debe ser transcripto
enteramente a JavaScript por eso Angular utiliza un transpilador (mezcla de traductor y
compilador) que traduce y compila el codigo TypeScript a JavaScript generando un directorio con
los archivos compilado .js que luego serán ejecutados por el browser, es por eso que cada vez
que se modifique un archivo TypeScript debe ser compilado nuevamente para poder ser
ejecutado cosa que no era necesario con JavaScript, algo que ya el propio lenguaje al ser
interpretado directamente por el browser nos permite.

A esto se lo conoce como superset, que es un lenguaje escrito sobre otro lenguaje, es decir no
se puede ejecutar directamente TypeScript sino que se hace a través del JavaScript que éste
genera.

10.2.2. Preparando el ambiente

Primero instalemos Angular-Cli, ejecutamos:


npm install -g @angular/cli

Esto instalará globalmente la herramienta angular-cli.

Si estás en Linux, quizás puedas necesitar sudo para instalar globalmente

Si todo salió bien, el comando ng --version nos mostrara las versiones instaladas:
ng --version

Autor: Ing. Mario Di Giorgio 19


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.3 Creando una nueva aplicación Angular 5

Ahora, escriba este comando para crear la nueva aplicación de Angular 5.


ng new books-store

Ir a la carpeta de aplicaciones recién creado.


cd books-store

Ejecute la aplicación Angular 5 escribiendo este comando.


ng serve

Autor: Ing. Mario Di Giorgio 20


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Ver al proceso de compilación de Angular que ejecuta el server de Angular 5 que nos proveerá
las páginas web en el puerto 4200.
** NG Live Development Server is listening on localhost:4200, open your browser
on http://localhost:4200/ **
Date: 2017-11-10T23:12:58.186Z -
Hash: a8de16d629b34a42bbda
Time: 9459ms
chunk {inline} inline.bundle.js (inline) 5.79 kB [entry] [rendered]
chunk {main} main.bundle.js (main) 20.6 kB [initial] [rendered]
chunk {polyfills} polyfills.bundle.js (polyfills) 553 kB [initial] [rendered]
chunk {styles} styles.bundle.js (styles) 33.8 kB [initial] [rendered]
chunk {vendor} vendor.bundle.js (vendor) 7.03 MB [initial] [rendered]

webpack: Compiled successfully.

Ahora, abra el navegador y vaya a ' http://localhost:4200 ' debería ver esta
página.

Autor: Ing. Mario Di Giorgio 21


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.4. Reemplace el servidor Web con Express.js

10.4.1 Crear servidor usando Express generator

Cerrar la aplicación Angular primero pulse 'ctrl + c' a continuación asegurese de tener instalado
el paquete de express-generator, ejecute el comando
npm install -g express-generator

Luego escriba
express --version

Deberá ver la versión del generador de servidor express, si logra verlo ahora es hora de
configurar el nuevo servidor de Node.js con Express, pero antes debe renombrar el archivo
package.json a package.json.angular para evitar que se sobrescriba y luego usamos el comando.
express .

se generarán los archivos necesarios para la ejecución del servidor express incluido el archivo
de inicio app.js.

Una vez terminada la ejecución abra los archivos package.json y package.json.angular

Vamos a combinarlos en un solo archivo package.json, debe pegar todas las dependencias de
express en el archivo de angular…

package.json
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"jade": "~1.11.0",
"morgan": "~1.9.0"
}

Copiar a package.json.angular quedando de la siguiente manera

Autor: Ing. Mario Di Giorgio 22


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

"dependencies": {
"@angular/animations": "~7.2.0",
"@angular/common": "~7.2.0",
"@angular/compiler": "~7.2.0",
"@angular/core": "~7.2.0",
"@angular/forms": "~7.2.0",
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~7.2.0",
"@angular/router": "~7.2.0",
"core-js": "^2.5.4",
"rxjs": "~6.3.3",
"tslib": "^1.9.0",
"zone.js": "~0.8.26",
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"jade": "~1.11.0",
"morgan": "~1.9.0"
},

También debe cambiar el script de start de esto…


"scripts": {
"start": "ng serve",

A esto…
"scripts": {
"start": "ng build && node ./bin/www",

Luego de guardar todos los cambios, asegúrese de eliminar el archivo package.json generado
por express-generator y renombrar el que acabamos de editar de package.json.angular a
package.json, ahora nuestro nuevo package.json se tiene que ver de la siguiente manera…
{
"name": "ng-test",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng build && node ./bin/www",
"build": "ng build",
"test": "ng test",

Autor: Ing. Mario Di Giorgio 23


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

"lint": "ng lint",


"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~7.2.0",
"@angular/common": "~7.2.0",
"@angular/compiler": "~7.2.0",
"@angular/core": "~7.2.0",
"@angular/forms": "~7.2.0",
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~7.2.0",
"@angular/router": "~7.2.0",
"core-js": "^2.5.4",
"rxjs": "~6.3.3",
"tslib": "^1.9.0",
"zone.js": "~0.8.26",
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"jade": "~1.11.0",
"morgan": "~1.9.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.13.0",
"@angular/cli": "~7.3.3",
"@angular/compiler-cli": "~7.2.0",
"@angular/language-service": "~7.2.0",
"@types/node": "~8.9.4",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.11.0",
"typescript": "~3.2.2"
}

Autor: Ing. Mario Di Giorgio 24


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Para asegurarse que los paquetes queden instalados correctamente ejecute el comando
npm install

Luego edite el archivo app.js y agregue las siguiente línea en la sección de variables:
var bodyparser = require('body-parser’);

Reemplace las siguientes líneas…


app.use(express.static(path.join(__dirname, 'public')));

Por
app.use(express.static(path.join(__dirname, 'dist/book-store')));

Tambien reemplace
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

Por
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));

10.4.2 Crear servidor Express manualmente

Si no posee el paquete de express generator o no desea instalarlo puede configurar los archivos
manualmente.
NOTA
EJECUTE ESTE PASO SOLO SI NO LO HA HECHO CON EL COMANDO DE EXPRESS GENERATOR

Escriba este comando para agregar módulos de Express.js y dependencias.


npm install --save express body-parser morgan http-errors serve-favicon

Autor: Ing. Mario Di Giorgio 25


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Luego, añadir carpeta bin y el archivo de www dentro de la carpeta bin.


md bin
copy NUL > bin/www.js

Abra y edite archivo www.js y añadir estas líneas de códigos.


#!/usr/bin/env node

/**
* Module dependencies.
*/

var app = require('../app');


var debug = require('debug')('mean-app:server');
var http = require('http');

/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');


app.set('port', port);

/**
* Create HTTP server.
*/

var server = http.createServer(app);

/**
* Listen on provided port, on all network interfaces.
*/

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
* Normalize a port into a number, string, or false.
*/

Autor: Ing. Mario Di Giorgio 26


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}

/**
* Event listener for HTTP server "error" event.
*/

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string' ?


'Pipe ' + port :
'Port ' + port;

// handle specific listen errors with friendly messages


switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

/**

Autor: Ing. Mario Di Giorgio 27


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

* Event listener for HTTP server "listening" event.


*/

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string' ?
'pipe ' + addr :
'port ' + addr.port;
debug('Listening on ' + bind);
}

Para hacer que el servidor funcione desde bin/www, abra y edite "package.json" y reemplazar el
valor de "start".
"scripts": {
"ng": "ng",
"start": "ng build && node ./bin/www",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},

Ahora, crear app.js en la raíz de la carpeta del proyecto.


copy NUL > app.js

Abra y edite app.js y añadir todas estas líneas de códigos.


var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var bodyParser = require('body-parser');

var book = require('./routes/book');


var app = express();
var publicdir = 'dist/books-store'

Autor: Ing. Mario Di Giorgio 28


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, publicdir));
app.set('view engine', 'html');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended':'false'}));
app.use(express.static(path.join(__dirname, publicdir)));
app.use('/books', express.static(path.join(__dirname, publicdir)));
app.use('/book', book);

// catch 404 and forward to error handler


app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page


res.status(err.status || 500);
res.render('error');
});

module.exports = app;

10.4.3 Agregar API Routes

A continuación, crearemos las rutas de la API para el manejo de los datos de un libro.
md routes
copy NUL > routes/book.js

Autor: Ing. Mario Di Giorgio 29


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Abra y edite el archivo 'routes/book.js' y añadir estas líneas de códigos.


var express = require('express');
var router = express.Router();

/* GET home page. */


router.get('/', function(req, res, next) {
res.send('Express RESTful API');
});

module.exports = router;

Ahora, ejecuta el servidor con este comando.


npm start

Verá la página de Angular anterior cuando usted apunte su navegador a


' http://localhost:3000 '. Cuando se cambia la dirección a 'http://localhost:3000/book'
podrás ver esta página.

Ahora, tenemos API RESTful con el compilado final de Angular 5.

10.5 Instalar y configurar Mongoose.js

Necesitamos acceder a datos de MongoDB. Para que se instale y configure Mongoose.js. En la


terminal escriba este comando después de parar el funcionamiento Express server con ‘ctrl’ + ‘c’.
npm install --save mongoose bluebird

Autor: Ing. Mario Di Giorgio 30


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Abra y edite 'app.js' y agregue estas líneas al final antes del module.exports.
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
mongoose.connect('mongodb://localhost:27017/books-store', { useNewUrlParser:
true, promiseLibrary: require('bluebird') })
.then(() => console.log('connection succesful'))
.catch((err) => console.error(err));

Si el servicio de MongoDB no está corriendo por default, debe ejecutarlo a mano.

Para ejecutar el servicio de MongoDB manualmente, vaya a otra terminal o línea de comandos..

(Recuerde que previamente debe instalar el servidor de MongoDB)


md data
mongod –dbpath ./data

Si obtiene el error de “No es un comando valido” es porque el directorio de MongoDB no está en


nuestra variable de entorno, para ello ejecute el siguiento comando.
set path=%path%;c:/Program Files/MongoDB/Server/{version}/bin

donde {version} es el número de versión del servidor de MongoDB,

luego de ejecutar este comando vuelva a intentar con


mongod –dbpath ./data

A continuación, puede probar la conexión a MongoDB, vuelva al otro terminal y vuelva a ejecutar
la aplicación NodeJs y verá este mensaje en el terminal.
connection succesful

Autor: Ing. Mario Di Giorgio 31


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Si todavía utiliza la biblioteca Promises de Mongoose, se mostrará esta advertencia en el


terminal.
(node:42758) DeprecationWarning: Mongoose: mpromise (mongoose's default promise
library) is deprecated, plug in your own promise library instead:
http://mongoosejs.com/docs/promises.html

Esa es la razón por qué hemos añadido módulos 'bluebird' y registrarlo como biblioteca Promises
de Mongoose .

10.5.1 Crear el modelo de Mongoose.js

Agregar una carpeta de modelos en la raíz de la carpeta del proyecto para mantener archivos de
modelo de Mongoose.js.
md models

Crear nuevo archivo de Javascript que se usará para el modelo Mongoose.js. Vamos a crear un
modelo de colección de libros.
copy NUL > models/Book.js

Ahora, abrir y editar el archivo Book.js y añadir la librería de Mongoose.


var mongoose = require('mongoose');

Luego agregar el modelo de datos.


var BookSchema = new mongoose.Schema({
isbn: String,
title: String,
author: String,
description: String,
published_year: String,
publisher: String,
updated_date: {

Autor: Ing. Mario Di Giorgio 32


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

type: Date,
default: Date.now
},
});

Este es el esquema de MongoDB que genera las colecciones de datos de libro.

Si quieres saber más sobre tipos de datos de esquema lo encontrarás aquí.

A continuación, exportar el esquema.


module.exports = mongoose.model('Book', BookSchema);

10.6 Crear rutas en Express para acceder a los datos del libro vía API
RESTful

Abra y edite nuevamente "routes/book.js" y reemplace todos los códigos con esto.
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Book = require('../models/Book.js');

/* GET ALL BOOKS */


router.get('/', function(req, res, next) {
Book.find(function (err, products) {
if (err) return next(err);
res.json(products);
});
});

/* GET SINGLE BOOK BY ID */


router.get('/:id', function(req, res, next) {
Book.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});

/* SAVE BOOK */
router.post('/', function(req, res, next) {
Book.create(req.body, function (err, post) {

Autor: Ing. Mario Di Giorgio 33


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

if (err) return next(err);


res.json(post);
});
});

/* UPDATE BOOK */
router.put('/:id', function(req, res, next) {
Book.findByIdAndUpdate(req.params.id, req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});

/* DELETE BOOK */
router.delete('/:id', function(req, res, next) {
Book.findByIdAndRemove(req.params.id, req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});

module.exports = router;

Ejecute de nuevo el servidor Express abriendo en otra terminal o línea de comandos para probar
la API Restful con este comando.
curl -i -H "Accept: application/json" localhost:3000/book

Si recibe esta respuesta del comando entonces la API REST está lista para funcionar.
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 2
ETag: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
Date: Fri, 10 Nov 2017 23:53:52 GMT
Connection: keep-alive

Ahora, vamos a rellenar la colección de libros con datos iniciales del API RESTful. Ejecute este
comando para rellenarlo.

Autor: Ing. Mario Di Giorgio 34


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5
curl -i -X POST -H "Content-Type: application/json" -d '{ "isbn":"123442123,
97885654453443","title":"Learn how to build modern web application with MEAN
stack","author": "Didin J.","description":"The comprehensive step by step
tutorial on how to build MEAN (MongoDB, Express.js, Angular 5 and Node.js) stack
web application from scratch","published_year":"2017","publisher":"Djamware.com"
}' localhost:3000/book

Usted verá esta respuesta a la terminal si tuvo éxito.


HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 415
ETag: W/"19f-SB/dEQyffaTjobOBJbvmwCn7WJA"
Date: Fri, 10 Nov 2017 23:58:11 GMT
Connection: keep-alive

{"__v":0,"isbn":"123442123, 97885654453443","title":"Learn how to build modern


web application with MEAN stack","author":"Didin J.","description":"The
comprehensive step by step tutorial on how to build MEAN (MongoDB, Express.js,
Angular 5 and Node.js) stack web application from
scratch","published_year":"2017","publisher":"Djamware.com","_id":"5a063d123cf079
2af12ce45d","updated_date":"2017-11-10T23:58:10.971Z"}MacBook-Pro:mean-angular5

10.7 Crear componente de Angular 5 para mostrar la lista de libros

Para crear el componente Angular 5, simplemente ejecute este comando.


ng g component book

El comando generará todos los archivos necesarios para construir el componente book que
también será agregado automáticamente a app.module.ts.
create src/app/book/book.component.css (0 bytes)
create src/app/book/book.component.html (23 bytes)
create src/app/book/book.component.spec.ts (614 bytes)
create src/app/book/book.component.ts (321 bytes)
update src/app/app.module.ts (390 bytes)

Autor: Ing. Mario Di Giorgio 35


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Antes de añadir alguna funcionalidad para el componente, es necesario añadir 'HttpClientModule'


a 'app.module.ts'.

Abra y edite 'src/app/app.module.ts' y añadir esta importación.


import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

Añadir a las importaciones '@NgModule' después de 'BrowserModule'.


imports: [
BrowserModule,
FormsModule,
HttpClientModule
],

Ahora, vamos a hacer una petición a la API RESTful book utilizando este módulo Angular
'HttpClient'.

Abra y edite 'src/app/book/book.component.ts' y añadir esta importación.


import { HttpClient } from '@angular/common/http';

Inyectar el módulo 'HttpClient' en el constructor, de ésta manera el objeto http se crea


automáticamente inyectándolo en el encabezado del constructor, ahora dicho objeto pasa a
formar parte del componente y lo podemos referenciar como this.http.
constructor(private http: HttpClient) { }

Añadir variable book antes del constructor.


books: any;

Añadir unas pocas líneas de códigos para obtener una lista de datos libro de RESTful API dentro
de la función 'ngOnInit', recuerden que el evento ngOnInit se ejecuta luego de que se crea el
componente y es el primer evento que se produce, aquí ya tenemos todos los elementos del
componente ya creados como por ejemplo el módulo http que inyectamos en el constructor.
ngOnInit() {

Autor: Ing. Mario Di Giorgio 36


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

this.http.get('/book').subscribe(data => {
this.books = data;
});
}

Como podemos ver usamos el módulo http que inyectamos en el constructor para hacer una
llamada http request con el comando GET, luego debemos subscribirnos a un evento de callback
con la función subscribe que nos devuelve la respuesta del servidor, este ¨subscribe¨ es una
función asíncrona por lo tanto llegará en un momento posterior a la llamada mientras tanto el
código siguiente se sigue ejecutando.

Ahora, podemos mostrar la lista de libros en la página.

Abra y edite 'src/app/book/book.component.html' y vuelva a colocar todas las etiquetas con esta
línea de etiquetas HTML.
<div class="container">
<h1>Book List</h1>
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let book of books">
<td>{{ book.title }}</td>
<td>{{ book.author }}</td>
<td>Show Detail</td>
</tr>
</tbody>
</table>
</div>

10.7.1 Instale Bootstrap y Font-Awesome

Autor: Ing. Mario Di Giorgio 37


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Para que se instale bootstrap directamente en nuestra aplicación Angular usaremos los
siguientes paquetes.
npm install --save bootstrap jquery popper.js font-awesome

luego para que se carguen los componente modificar la configuración en el archivo angular.json
para que se carguen al iniciar la aplicación.
"styles": [
"src/styles.scss",
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/font-awesome/css/font-awesome.css"
]

Tambien debemos agregar la importación de los componentes de Bootstrap en la configuración


de estilos, editar el archivo src/styles.scss y agregar las siguientes líneas
// Option A: Include all of Bootstrap
@import "../node_modules/bootstrap/scss/bootstrap";

10.7.2 Configurar bootstrap como hoja de estilos en INDEX.HTML

Otro método es modificar las etiquetas HTML de la página de inicio para incluir los estilos de
Bootstrap CSS.
NOTA
MODIFIQUE EL ARCHIVO INDEX.HTML SOLO SI NO HA INSTALADO BOOTSTRAP DESDE NPM Y
CONFIGURADO COMO SE INDICA EN EL PASO ANTERIOR

Abra y edite 'src/index.html' y añadir la biblioteca Bootstrap CSS y JS.


<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>MeanAngular5</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">


Autor: Ing. Mario Di Giorgio 38
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

<link rel="icon" type="image/x-icon" href="favicon.ico">


<!-- Latest compiled and minified CSS -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-
BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-
theme.min.css"
integrity="sha384-
rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous">
</head>

<body>
<app-root></app-root>
<!-- Latest compiled and minified JavaScript -->
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-
Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous">
</script>
</body>

</html>

10.7.3 Crear en Angular 5 rutas al componente Book

Para utilizar el componente book como página de inicio predeterminada, abra y edite
'src/app/app.module.ts' agregue la importación para el enrutamiento.
import { RouterModule, Routes } from '@angular/router';

Crear constante router para rutear el componente book antes de '@NgModule'.


const appRoutes: Routes = [
{
path: 'books',
component: BookComponent,
Autor: Ing. Mario Di Giorgio 39
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

data: { title: 'Book List' }


},
{ path: '',
redirectTo: '/books',
pathMatch: 'full'
}
];

A los ¨imports¨ de @NgModule, agregar constante de rutas.


imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],

Para activar las rutas en Angular 5, abrir y editar 'src/app/app.component.html' entonces Cambie
todo el código con esto.
<router-outlet></router-outlet>

La etiqueta <router-outlet> es propia de Angular y le indica que allí se generarán y mostrarán


todos los componentes que se enruten desde la url de la aplicación.

Ahora, tenemos que probar nuestra aplicación con sólo la página de lista de libros.

Ejecutar la aplicación.
npm start

Debería ver esta página apuntando a ' http://localhost:3000 «o» http://localhost:3000/books .

Autor: Ing. Mario Di Giorgio 40


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.8 Crear componentes de Angular para ABM de libros.

10.8.1 Componente de Detalles

Igual a la sección anterior, escriba este comando para generar el nuevo componente.
ng g component book-detail

10.8.1.1 Configurar componente de Detalles

Abrir y editar 'src/app/book-detail/book-detail.component.ts'.

Reemplace el código con esto.


import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';

@Component({
selector: 'app-book-detail',
templateUrl: './book-detail.component.html',
styleUrls: ['./book-detail.component.css'],
encapsulation: ViewEncapsulation.None
})
export class BookDetailComponent implements OnInit {

book = {};

constructor(private route: ActivatedRoute, private http: HttpClient) { }


Autor: Ing. Mario Di Giorgio 41
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

ngOnInit() {
this.getBookDetail(this.route.snapshot.params['id']);
}

getBookDetail(id) {
this.http.get('/book/'+id).subscribe(data => {
this.book = data;
});
}

Los módulos de ActivatedRoute y HttpClient son inyectados en el constructor, el de HttpClient ya


vimos como se usa para hacer llamadas desde mi componente hacia afuera ahora vemos como
ActivatedRoute me devuelve información sobre quien ha llamado desde afuera hacia mi
componente, es decir el proceso inverso de HttpClient.

Con este modulo podremos obtener por ejemplo los parámetros que fueron enviados y los datos
del body del request.

En este caso obtenemos el parametro id con el codigo


this.route.snapshot.params['id']

Dicho parámetro es enviado desde el ruteo o desde el [routerLink] que veremos en el siguiente
punto.

10.8.1.2 Link de ruteo al componente Detalles

Editar el archivo 'src/app/book/book.component.html' y cambie la línea <td>Show Detail<td>.


<tr *ngFor="let book of books">
<td>{{ book.title }}</td>
<td>{{ book.author }}</td>
<td>Show Detail</td>
</tr>

Por esto..
<tr *ngFor="let book of books">
<td>{{ book.title }}</td>
<td>{{ book.author }}</td>
<td><a class="btn btn-large btn-info fa fa-search-plus" [routerLink]="['/book-
detail', book._id]" routerLinkActive="router-link-active">Show details</a></td>

Autor: Ing. Mario Di Giorgio 42


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

</tr>

Fijarse que el atributo [routerLink] apunta a la ruta del componente “book-detail” y le pasa como
parametro el ID el “book._id” del libro que se está listando con el ngFor.

El parámetro deberá ser declarado en el ruteo tal como se muestra en el punto 10.8.1.4 Ruteo
para el componente de Detalle.

10.8.1.3 HTML para el componente Detalles

Abrir y editar 'src/app/book-detail/book-detail.component.html'.

Reemplace el código con esto.


<div class="row justify-content-center m-5">
<div class="col-4">
<div class="d-flex card shadow-lg">
<div class="card-header text-light bg-dark">
<h1 class="card-title">{{ book.title }}</h1>
</div>
<div class="card-body">
<dl class="list">
<dt>ISBN</dt>
<dd>{{ book.isbn }}</dd>
<dt>Author</dt>
<dd>{{ book.author }}</dd>
<dt>Publisher</dt>
<dd>{{ book.publisher }}</dd>
<dt>Price</dt>
<dd>{{ book.price }}</dd>
<dt>Update Date</dt>
<dd>{{ book.updated_at }}</dd>
</dl>
</div>
<div class="card-footer">
<a class="btn btn-lg btn-dark"
[routerLink]="['/books']">Lista</a>
</div>
</div>
</div>
</div>

Autor: Ing. Mario Di Giorgio 43


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.8.1.4 Ruteo para el componente Detalles

Agregar el ruteo a 'src/app/app.module.ts'.


const appRoutes: Routes = [
{
path: 'books',
component: BookComponent,
data: { title: 'Book List' }
},
{
path: 'book-details/:id',
component: BookDetailComponent,
data: { title: 'Book Details' }
},
{ path: '',
redirectTo: '/books',
pathMatch: 'full'
}
];

El ruteo al componente BookDetailComponent lleva como ruta “book-details/:id” donde la parte


de la ruta que corresponde a :id es un parámetro variable, allí debemos entonces rutear por
ejemplo desde el [routerLink] pasándole la ruta y el parametro ID, por ejemplo
[routerLink]="['/book-detail', book._id]"

Tal cual como se muestra en el punto 10.8.1.2.

10.8.2 Componente agregar nuevo libro

Para crear un componente para agregar un nuevo libro, escriba este comando como de
costumbre.
ng g component book-create

10.8.2.1 Agregar enlace a componente nuevo libro

Autor: Ing. Mario Di Giorgio 44


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Añadir el enlace ‘book-create' en 'src/app/book/book.component.html'.

Reemplace el <h1> con esto.


<h1>Book List
<a [routerLink]="['/book-create']" class="btn btn-default btn-lg">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</a>
</h1>

10.8.2.2 Configurar componente nuevo libro

Ahora, abrir y editar 'src/app/book/book-create.component.ts' entonces reemplace todo el


contenido con este código.
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-book-create',
templateUrl: './book-create.component.html',
styleUrls: ['./book-create.component.css'],
encapsulation: ViewEncapsulation.None
})
export class BookCreateComponent implements OnInit {

book = {};

constructor(private http: HttpClient, private router: Router) { }

ngOnInit() {
}

saveBook() {
this.http.post('/book', this.book)
.subscribe(res => {
let id = res['_id'];
this.router.navigate(['/book-details', id]);
}, (err) => {
console.log(err);

Autor: Ing. Mario Di Giorgio 45


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

}
);
}

Aquí podemos ver como hemos inyectado un nuevo módulo el Router referenciado por el objeto
this.router, así como vimos que HttpClient nos permite enviar peticiones http hacia afuera de
nuestra aplicación Angular, el módulo Router nos permite hacer lo mismo pero para navegar
dentro de las rutas de nuestra aplicación Angular, es decir ruteos internos a otros componentes
Angular.

Vemos entonces como una ves que realizamos el post del nuevo libro y nos subscribimos al
callback de la respuesta, ésta nos llega con el dato del nuevo _id del libro que se creó y entonces
podemos navegar al componente de BookDetailsComponent usando
this.router.navigate(['/book-details', id]);

Entonces navigate cumple la misma función que el [routerLink] que declaramos en el html solo
que éste lo hacemos desde el código del componente.

Además, el módulo Router proporciona datos para luego ser capturados por el módulo
ActivatedRoute y genera tambien el historial de navegación del browser lo que permite que
podamos navegar hacia atrás usando el botón Back del mismo browser.

10.8.2.3 HTML para nuevo libro

Edite 'Src/app/book-create/book-create.component.html' reemplazar todo con este HTML.


<div class="container">
<h1>Add New Book</h1>
<div class="row">
<div class="col-md-6">
<form (ngSubmit)="saveBook()" #bookForm="ngForm">
<div class="form-group">
<label for="name">ISBN</label>
<input type="text" class="form-control"
[(ngModel)]="book.isbn" name="isbn" required>

Autor: Ing. Mario Di Giorgio 46


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

</div>
<div class="form-group">
<label for="name">Title</label>
<input type="text" class="form-control"
[(ngModel)]="book.title" name="title" required>
</div>
<div class="form-group">
<label for="name">Author</label>
<input type="text" class="form-control"
[(ngModel)]="book.author" name="author" required>
</div>
<div class="form-group">
<label for="name">Published Year</label>
<input type="number" class="form-control"
[(ngModel)]="book.published_year" name="published_year"
required>
</div>
<div class="form-group">
<label for="name">Publisher</label>
<input type="text" class="form-control"
[(ngModel)]="book.publisher" name="publisher" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success"
[disabled]="!bookForm.form.valid">Save</button>
</div>
</form>
</div>
</div>
</div>

Vemos aquí un claro ejemplo de bindeo doble tanto desde el codigo hacia el browser como del
browser hacia el código con el uso de la directiva [(ngModel)], es decir que si modificamos el
valor del objeto book desde el código del componente automáticamente se verá reflejado en la
página web y si desde la página web cambiamos el valor del book también se verá reflejado
automáticamente desde el código.

También hay que tener en cuenta la directiva (ngSubmit) del form y el nombre que se le aplica al
formulario con el atributo #[nombreForm]=”ngForm” de esta manera podemos referenciar a

Autor: Ing. Mario Di Giorgio 47


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

estados del formulario directamente con el objeto [nombreForm].form en este caso llamado
bookForm.

10.8.2.4 Ruteo para el componente de nuevo libro

Agregar ruteo en 'src/app/app.module.ts'.


const appRoutes: Routes = [
{
path: 'books',
component: BookComponent,
data: { title: 'Book List' }
},
{
path: 'book-details/:id',
component: BookDetailComponent,
data: { title: 'Book Details' }
},
{
path: 'book-create',
component: BookCreateComponent,
data: { title: 'Create Book' }
},
{ path: '',
redirectTo: '/books',
pathMatch: 'full'
}
];

10.8.3 Componente editar libro

Como de costumbre, se generan componentes para editar libro. Escriba este comando para
hacerlo.
ng g component book-edit

10.8.3.1 Agregar enlace a editar libro

Autor: Ing. Mario Di Giorgio 48


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Abrir y editar otra vez 'src/app/book-details/book-details.component.html' y añadir routeLink en la


última línea.
<div class="row">
<div class="col-md-12">
<a [routerLink]="['/book-edit', book._id]" class="btn btn-
success">EDIT</a>
</div>
</div>

10.8.3.2 Configurar componente de editar libro

Ahora, abrir y editar 'src/app/book-edit/book-edit.component.ts' luego cambie todos el código por


esto.
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-book-edit',
templateUrl: './book-edit.component.html',
styleUrls: ['./book-edit.component.css'],
encapsulation: ViewEncapsulation.None
})
export class BookEditComponent implements OnInit {

book = {};

constructor(private http: HttpClient, private router: Router, private route:


ActivatedRoute) { }

ngOnInit() {
this.getBook(this.route.snapshot.params['id']);
}

getBook(id) {
this.http.get('/book/'+id).subscribe(data => {
this.book = data;
});
}

updateBook(id, data) {
this.http.put('/book/'+id, data)
Autor: Ing. Mario Di Giorgio 49
UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

.subscribe(res => {
let id = res['_id'];
this.router.navigate(['/book-details', id]);
}, (err) => {
console.log(err);
}
);
}

10.8.3.3 HTML de editar libro

Abra y edite 'src/app/book-edit/book-edit.component.html' y sustituir todos el código con esto.


<div class="container">
<h1>Edit Book</h1>
<div class="row">
<div class="col-md-6">
<form (ngSubmit)="updateBook(book._id)" #bookForm="ngForm">
<div class="form-group">
<label for="name">ISBN</label>
<input type="text" class="form-control"
[(ngModel)]="book.isbn" name="isbn" required>
</div>
<div class="form-group">
<label for="name">Title</label>
<input type="text" class="form-control"
[(ngModel)]="book.title" name="title" required>
</div>
<div class="form-group">
<label for="name">Author</label>
<input type="text" class="form-control"
[(ngModel)]="book.author" name="author" required>
</div>
<div class="form-group">
<label for="name">Published Year</label>
<input type="number" class="form-control"
[(ngModel)]="book.published_year" name="published_year"
required>
</div>
<div class="form-group">

Autor: Ing. Mario Di Giorgio 50


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

<label for="name">Publisher</label>
<input type="text" class="form-control"
[(ngModel)]="book.publisher" name="publisher" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success"
[disabled]="!bookForm.form.valid">Update</button>
</div>
</form>
</div>
</div>
</div>

10.8.3.4 Ruteo para el componente de editar libro

Agregar ruteo en 'src/app/app.module.ts' por lo que debe quedar como esto.


const appRoutes: Routes = [
{
path: 'books',
component: BookComponent,
data: { title: 'Book List' }
},
{
path: 'book-details/:id',
component: BookDetailComponent,
data: { title: 'Book Details' }
},
{
path: 'book-create',
component: BookCreateComponent,
data: { title: 'Create Book' }
},
{
path: 'book-edit/:id',
component: BookEditComponent,
data: { title: 'Edit Book' }
},
{ path: '',
redirectTo: '/books',
pathMatch: 'full'
}
];

Autor: Ing. Mario Di Giorgio 51


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.8.4 Función de eliminar libro

10.8.4.1 Agregar módulo de ruteo e inyectar en el componente Detalles

Abrir y editar ' src/app/book-detail/book-detail'.component.ts entonces añadir módulo 'Router' de


'@angular/router'.
import { ActivatedRoute, Router } from '@angular/router';

Inyectar 'Router' en los parámetros del constructor.


constructor(private router: Router, private route: ActivatedRoute, private http:
HttpClient) { }

10.8.4.2 Agregar función de eliminar en el componente de Detalles

Añadir esta función para borrar un libro.


deleteBook(id) {
this.http.delete('/book/'+id)
.subscribe(res => {
this.router.navigate(['/books']);
}, (err) => {
console.log(err);
}
);
}

10.8.4.3 Agregar enlace para eliminar libro en componente Detalle

Añadir botón de delete en 'src/app/book-detail/book-detail.component.html' a continuación del


enlace de edición.
<div class="row">

Autor: Ing. Mario Di Giorgio 52


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

<div class="col-md-12">
<a [routerLink]="['/book-edit', book._id]" class="btn btn-
success">EDIT</a>
<button class="btn btn-danger" type="button"
(click)="deleteBook(book._id)">DELETE</button>
</div>
</div>

10.9 Ejecute y pruebe la aplicación CRUD de Angular 5

Ahora, es un tiempo para probar la aplicación CRUD de (Angular 5).


npm start

Y aquí estamos.

Autor: Ing. Mario Di Giorgio 53


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Autor: Ing. Mario Di Giorgio 54


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

10.10 Modificar el componente de creación de libro para usar


validadores especiales.

Abrir y editar ‘scr/app/app-module.ts’

Agregar el import de ReactiveFormsModule a los modulos de forms.


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

Agregar los import de dichos módulos en el @NgModule


imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
),
FormsModule,
ReactiveFormsModule
],

Abrir y editar ‘src/app/book-create/book-create.component.ts’

Agregar el import de los módulos de validación.


import { Validators, FormGroup, FormControl } from '@angular/forms';

Además, agregar la variable bookForm para guardar los datos de validación antes del
constructor.
bookForm: FormGroup;

Agregar dentro del ngOnInit() el siguiente código.


this.bookForm = new FormGroup({

Autor: Ing. Mario Di Giorgio 55


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

isbn: new FormControl('', Validators.required),


title: new FormControl('', Validators.required),
author: new FormControl('', Validators.required),
published_year: new FormControl('', [Validators.required,
Validators.min(1900), Validators.max(2100)]),
publisher: new FormControl('', Validators.required)
});

Con esto validaremos los campos el validador Validators.required especifica que el campo debe
tener un dato cargado de lo contrario el formulario quedará marcado como inválido.

El validador Validators.min y Validators.max validan rangos mínimos y máximo de entrada de


datos.

Abrir y editar ‘src/app/book-create/book-create.component.html’

Reemplazar todo el código con lo siguiente.


<div class="container">
<h1>Add New Book</h1>
<div class="row">
<div class="col-md-6">
<form [formGroup]="bookForm" (ngSubmit)="saveBook(bookForm.value)"
novalidate>
<div class="form-group"
[ngClass]="{ 'has-error': bookForm.controls['isbn'].errors &&
(bookForm.controls['isbn'].touched || bookForm.controls['isbn'].dirty)}">
<label for="name">ISBN</label>
<input type="text" class="form-control"
[(ngModel)]="book.isbn" name="isbn" formControlName="isbn"
required>
<div *ngIf="bookForm.controls['isbn'].errors &&
bookForm.controls['isbn'].touched">
<div class="text-danger"
*ngIf="bookForm.controls['isbn'].hasError('required')">
Enter the ISBN.
</div>
</div>
</div>
<div class="form-group"
[ngClass]="{ 'has-error': bookForm.controls['title'].errors
&& (bookForm.controls['title'].touched || bookForm.controls['title'].dirty)}">
<label for="name">Title</label>

Autor: Ing. Mario Di Giorgio 56


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

<input type="text" class="form-control"


[(ngModel)]="book.title" name="title"
formControlName="title" required>
<div *ngIf="bookForm.controls['title'].errors &&
bookForm.controls['title'].touched">
<div class="text-danger"
*ngIf="bookForm.controls['title'].hasError('required')">
Enter the Book Title.
</div>
</div>
</div>
<div class="form-group"
[ngClass]="{ 'has-error': bookForm.controls['author'].errors
&& (bookForm.controls['author'].touched || bookForm.controls['author'].dirty)}">
<label for="name">Author</label>
<input type="text" class="form-control"
[(ngModel)]="book.author" name="author"
formControlName="author" required>
<div *ngIf="bookForm.controls['author'].errors &&
bookForm.controls['author'].touched">
<div class="text-danger"
*ngIf="bookForm.controls['author'].hasError('required')">
Enter the Author name.
</div>
</div>
</div>
<div class="form-group"
[ngClass]="{ 'has-error':
bookForm.controls['published_year'].errors &&
(bookForm.controls['published_year'].touched ||
bookForm.controls['published_year'].dirty)}">
<label for="name">Published Year</label>
<input type="number" class="form-control"
[(ngModel)]="book.published_year" name="published_year"
formControlName="published_year" required>
<div
*ngIf="bookForm.controls['published_year'].errors &&
bookForm.controls['published_year'].touched">
<div class="text-danger"
*ngIf="bookForm.controls['published_year'].hasError('required')">
Enter a year.
</div>
<div class="text-danger"
*ngIf="bookForm.controls['published_year'].hasError('min')">
Minimum required number is 1900.

Autor: Ing. Mario Di Giorgio 57


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

</div>
<div class="text-danger"
*ngIf="bookForm.controls['published_year'].hasError('max')">
Minimum required number is 2100.
</div>
</div>
</div>
<div class="form-group"
[ngClass]="{ 'has-error':
bookForm.controls['publisher'].errors && (bookForm.controls['publisher'].touched
|| bookForm.controls['publisher'].dirty)}">
<label for="name">Publisher</label>
<input type="text" class="form-control"
[(ngModel)]="book.publisher" name="publisher"
formControlName="publisher" required>
<div *ngIf="bookForm.controls['publisher'].errors &&
bookForm.controls['publisher'].touched">
<div class="text-danger"
*ngIf="bookForm.controls['publisher'].hasError('required')">
Enter the Publisher name.
</div>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success"
[disabled]="!bookForm.valid">Save</button>
</div>
</form>
</div>
</div>
</div>

De esta manera estaremos validando cada campo usando los modificadores


[formGroup]=”bookForm” al form y el atributo formControlName=”name” a cada input.

10.11 Ejecute y pruebe la aplicación Angular 5 Completa

Ahora, es un tiempo para probar nuevamente la aplicación (Angular 5).


npm start

Autor: Ing. Mario Di Giorgio 58


UNIVERSIDAD TECNOLÓGICA NACIONAL Diplomatura en Desarrollo WEB
Facultad Regional Córdoba Módulo: API Rest con NodeJS y SPA con Angular 5

Navegue al sitio http://localhost:3000 y verifique que se ejecute el sitio con los formularios
de lista de libros, crear, editar y detalles.

Autor: Ing. Mario Di Giorgio 59

También podría gustarte