Introducción al desarrollo Web: Frontend con Angular 6
1. Introducción al desarrollo
Web con Angular 6 y NodeJs
- Frontend -
Dra. Gabriela BOSETTI gbosetti@lifia.info.unlp.edu.ar
Jornadas de Informatica UARG-UNPA
Octubre, 2018
2. Goals of this class
a. Comprender el desarrollo frontend
b. Utilizar un framework Model-View-Controller (MVC)
c. Ser capaz de desarrollar una Single Page App (SPA)
1. Angular 6 con Angular cli
2. TypeScript
3. Bootstrap
4. Services
5. Routing
d. Crear y hacer push a un repo
e. Crear el punto de extensión para migrar la SPA con Web
services en las próximas clases
2
3. SPA vs app Web tradicional
Home
Page 1
Page 2
To-do list
Mockup creado con https://app.mockflow.com
3
4. Modelo-Vista-Controlador (MVC)
Modelo
1. Contiene los datos a mostrar
2. Validación, manipulación de los datos
(CRUD)
Vista
1. Presentación, interfaz de usuario (UI)
2. Visualiza los datos del modelo
Controlador
1. Maneja las interacciones del usuario
2. Actualiza el modelo y la vista
Modelo
Vista
Controlador
interactúa
actualiza
notificanotifica
1
2
3
4
4
5. Arquitectura de Angular: MV...C?
Modelo
Cuenta Cliente
CajaDeA
horros
CuentaCorriente
Vista
...
interacts
notifiesmanipulates
updates
1
23
4
RemoteAccountService
e.g. storage en
el backend
Componentes TypeScript
Manejando interacciones del usuario
Componentes TypeScript
Persistiendo datos a presentar
5
notifies
5
6. TypeScript
TypeScript es la versión ES6 de JavaScript + características extra
● ES5
○ prototypes
● ES6
○ classes
○ modules
○ arrow functions
○ promises
○ transpiled to ES5
● Typescript
○ ES6
○ Typed variables
TypeScript
Ecma 6
Ecma 5
6
7. Herencia ES5 ( hay más maneras)
function Shape(x, y) {
this.setLocation(x, y);
}
Shape.prototype.setLocation = function(x, y) {
this.x = x;
this.y = y;
};
function Shape(x, y) {
this.setLocation = function(x, y) {
this.x = x;
this.y = y;
};
this.setLocation(x, y);
};
PrototiposFunción
function Circle(x, y){...};
Circle.prototype =
Shape.prototype;
function Circle(x,y){
Shape.call(this, x,y);
}
7
12. El entorno: alternativas
a. Editor online https://stackblitz.com
b. Instalación local en VM
c. Una instalación local
i. Quitá versiones anteriores
sudo apt-get autoremove npm node
ii. Instalá node 10.x
sudo apt-get install curl
curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt-get update
sudo apt-get install nodejs
iii. Verificá que tenés la última versión
sudo npm i npm
iv. Instalá angular-cli
sudo npm install -g @angular/cli@latest
online
local
vm
12
13. Initial skeleton
Crear el esqueleto mínimo
ng new todolist --minimal
En caso de tener el error «write
after end», ejecutá
npm update
Para construir la app + levantar
el server
sudo ng serve --open
localvm
13
14. Editar el componente raíz
Ej. cambiar el título a
mostrar por “To-do list”
vmonline local
14
15. Crear otro componente
Crear un componente “list” que presentará una lista de “items”
online
ng generate component todolist
localvm
15
16. El modelo: cómo crear una clase
Item
+ name: String
- creationDate: Date
+ constructor(name: String): Item
+ creationDate(): Date
export class Item {
name: String;
constructor(name: String){
this.name = name;
}
}
vmonline local
Crear un nuevo archivo: src/app/model/Item.ts
16
18. El ItemsComponent
Importar la clase Item
import { Item } from '../../model/Item';
Agregar la propiedad de instancia “items” en la clase
ItemsComponent
items : Item[];
Inicializarla desde el constructor
this.items = [
new Item("Buy pendrives"),
new Item("Buy backpacks"),
new Item("Rent projectors")
];
vmonline local
18
19. <div class="content">
<!-- LIST OF ITEMS -->
<div class="row justify-content-md-center">
<ul class="list-group">
<li class="list-group-item list-group-item-action" *ngFor="let item of items" >
<span>{{item.name}}</span>
<span class="badge">{{item.creationDate | date}}</span>
<div class="pull-right">
<button class="btn btn-primary btn-xs fa fa-pencil" (click)="onEdit(item)"></button>
<button class="btn btn-danger btn-xs fa fa-trash-o" (click)="onRemove(item)"></button>
</div>
</li>
</ul>
</div>
<!-- NEW ITEM -->
<div class="row justify-content-md-center">
<nav>
<a class="pull-right">New item</a>
</nav>
</div>
</div>
La vista:código base de la lista
vmonline local
NgFor: https://angular.io/api/common/NgForOf
Filters: https://docs.angularjs.org/api/ng/filter
Templates: https://angular.io/guide/template-syntax
Template binding
Filter
19
22. <li class="list-group-item list-group-item-action" *ngFor="let item of items" >
<span>{{item.name}}</span>
<span class="badge">{{item.creationDate | date}}</span>
<div class="pull-right">
<button class="btn btn-primary btn-xs fa fa-pencil"></button>
<button class="btn btn-danger btn-xs fa fa-trash-o" (click)="onRemove(item)"></button>
</div>
</li>
Abrir la
consola
Web
La vista: binding de datos y eventos
vmonline local
Interpolation
(Data-binding)
Template statement
(event binding)
22
23. Controlador
Modelo
El controlador: agregando comportamiento
Agregar el siguiente método al TodolistComponent
onRemove(anItem){
this.items = this.items.filter(item => item !== anItem);
}
Pero, ¿es conveniente
que el controlador
directamente interactúe
con los datos a ser
almacenados?
¿Y si necesitamos
cambiar el mecanismo de
almacenamiento?
Item
+ name: String
- creationDate: Date
+ constructor(name: String): Item
+ creationDate(): Date
TodolistComponent
*
AbstractItemService
23
25. Servicios
Los componentes no deberían tener la responsabilidad de recuperar o
guardar datos directamente.
AbstractItemsService
MockItemsService
HttpItemsService
LocalItemsService
online
ng generate service
_services/abstractItems
localvm
25
26. Buenas prácticas
Una sola clase por archivo
Agrupar servicios en “paquetes”. Ej.
todos lo relacionado a ítems en una
carpeta, todo lo de autenticación en
otra.
Todos los servicios van a “_services”
26
27. Extendiendo clases en TS
AbstractItemsService
MockItemsService
vmonline local
abstract class AbstractItemService {
constructor() { }
abstract getItems(): Promise<Item[]>;
}
export class MockItemService extends AbstractItemService {
items: Item[];
constructor(){
super();
this.items = [
new Item("Buy pendrives")
];
}
getItems(): Item[] {};
}
ng generate service
_services/mockItems
27
28. Promesas/Observables en Javascript
TodolistComponent
AbstractItemsService
MocktemsService
Pero lo que retorna un servicio podría tener algún
tipo de delay… Esto debería poder adaptarse y
funcionar en modo asincrónico.
¿Cómo sabe el componente en qué momento
renderizar los datos con lo que devuelve el servicio?
getItems(): Promise<Item[]> {
return new Promise((resolve) => {
resolve(this.items);
});
};
Considerá este caso con un XMLHttpRequest
28
getItems():Observable<Item[]>{
return new Observable((observable) => {
observable.next(this.items);
observable.complete();
});
};
Alternativa con Observables:
https://github.com/gbosetti/demo-frontend
29. Promesas/Observables en Javascript
export class TodolistComponent implements OnInit {
...
constructor() {
this.service = new MockItemService();
this.updateLocalItems();
}
updateLocalItems(){
this.service.getItems().then(items => this.items = items);
}
}
arrow
function
Después de que la Promise fué
ejecutada satisfactoriamente
29
Alternativa con
Observables!
https://github.com/gbo
setti/demo-frontend
.subscribe
32. El componente “New item”
Crear un tercer componente:
ng generate component newItem
localvm
online
32
33. app.module.ts
import { AppRoutingModule } from
'@angular/router';
imports: […, AppRoutingModule ]
Generar el router
ng generate module app-routing --flat
--module=app
En el html principal, reemplazar:
<app-todolist></app-todolist>
con:
<router-outlet></router-outlet>
online
vm
localvm
online local
33
37. Formularios con Angular
Dos formas de crear formularios:
1. Template-driven forms (FormsModule). Creando elementos html y
usando directivas para enlazar su valor a variables del componente.
a. Usa ngModel, required, name
2. Reactive forms (ReactiveFormsModule). Se define un template, pero la
estructuras del form es definida mediante código
a. Bueno en caso de forms con múltiples campos
b. Evita directivas, como ngModel
c. Usa [formGroup] y formControlName en la vista
37
42. Sobre el repo
Al menos, un readme.md que mencione
1. De qué se trata el proyecto
2. Cómo instalar lo necesario
3. Cómo usar lo que instalaron
4. Un ejemplo donde se muestra un
uso concreto
Por ejemplo,
https://github.com/gbosetti/todo-list-mongo-backend
42
50. Services: session y auth
ng generate service _services/session --module app.module.ts
SessionService
es solo responsable de almacenar los
datos de la sesión.
public accessToken: string;
public name: string;
public destroy(): void {
this.accessToken = undefined;
this.name = undefined;
}
11
AuthService
es responsable de la lógica de
autenticación.
50
51. Variables de entorno
From components
import {environment} from '../../environments/environment';
From terminal
ng serve
ng serve --configuration=production
Mirar
angular.json
51
53. Introducción al desarrollo
Web con Angular 6 y NodeJs
- Frontend -
Dra. Gabriela BOSETTI gbosetti@lifia.info.unlp.edu.ar
Jornadas de Informatica UARG-UNPA
Octubre, 2018