Angular
Introducción a Angular
Angular es un framework para desarrollo SPA, permite extender el HTML con etiquetas propias.
Angular-CLI
Proyecto
- src: Fuentes de la aplicación
- node_modules: Librerías y herramientas descargadas
- e2e: Testing end to end
- package.json: Configuración de librerías y herramientas
- angular-cli.json: Configuración de angular-cli
- app: Carpeta que contiene los ficheros fuente principales de la aplicación.
- Borraremos su contenido y le sustituiremos por los ejemplos
- assets: Ficheros que se incluyen en el bundle cuando la aplicación se empaqueta para producción
- main.ts: Fichero principal de la aplicación. No es necesario modificarle
- favicon.ico: Icono de la aplicación
- index.html: Página principal. No es necesario modificarle
- styles.css: Estilos globales de la app
- tsconfig.json: Configuración del compilador TS
TypeScript
JavaScript ES6 con tipos opcionales que pueden avisar de
potenciales
problemas.
Componentes
- Un componente es una nueva etiqueta HTML con una vista y una lógica definidas por el desarrollador.
- La vista es una plantilla (template) en HTML con elementos especiales.
- La lógica es una clase TypeScript vinculada a la vista.
La vista del componente (HTML) se genera en función de su estado (atributos de la clase).
Recursos de la app
Los recursos (imágenes, fonts..) deben colocarse en una carpeta src/assets para que estén accesibles en desarrollo y cuando se genera el paquete de producción.
Ejecución de lógica
Se puede ejecutar un método ante un evento producido en la vista del componente.
Sintaxis de los templates
Data Binding
Templates
Los templates permiten definir la vista en función de la información del componente.
- Visualización condicional
- Repetición de elementos
- Safe navigation operator
- Estilos
- Formularios
Visualización condicional
<p *ngIf="visible">Text</p>
Repetición de elementos
<div *ngFor="let elem of elems">{{elem.desc}} </div>
Directivas
Las directivas modifican a los elementos en los que se incluyen.
Existen muchas directivas predefinidas y podemos
programar
nuestras propias directivas.
Las directivas estructurales empiezan por * y modifican el DOM del documento (*ngIf, *ngFor, *ngSwitch).
No se pueden incluir dos directivas estructurales (de tipo *) en el mismo elemento.
Safe Navigation Operator
Para evitarlo existe el safe navigator operator. Undefined se representa como cadena vacía
User’s name: {{user?.name}}
Estilos CSS
Globalmente asociado al index.html
Si creamos un fichero src/styles.css se incluirá de forma automática en el index.html.
Definir CSS en Componente
En la propiedad styles o styleUrls de @Component
Asociar la clase de un elemento a un atributo string
<h1 [class]="className">Title!</h1>
Activar una clase concreta con un atributo boolean
<h1 [class.red]="redActive">Title!</h1>
Asociar la clase de un elemento a un mapa
<p [ngClass]="pClasses">Text</p>
Asociar un estilo concreto a un atributo
<p [style.backgroundColor]="pColor">Text</p>
Asociar un estilo concreto a un atributo
<p [ngStyle]="getStyles()">Text</p>
Formularios
- Vincular un control del formulario a un atributo del componente
- Acceso a los controles desde el código para leer y modificar su estado
- Mecanismos avanzados con validación con ngControl
Data binding en campo de texto
Data binding en campo de texto
-
Se vincula el control a un atributo del componente
con [(ngModel)] -
Cualquier cambio en el control se refleja en el valor del atributo
<input type="text" [(ngModel)]="name">
Data binding en checkbox
Cada control se asocia con [(ngModel)] a un atributo booleano y su valor depende de si está “checked”
<input type="checkbox" [(ngModel)]="booleano"/>
Data binding en botones de radio
Todos los botones del mismo grupo se asocian al mismo atributo con [(ngModel)]
<input type="radio" name="gender" [(ngModel)]="gender" value="Male">
Acceso a los controles desde el código
Un elemento del template puede asociarse a una variable: Template reference variables.
Podemos usar esa variable en el código del template para manejar ese elemento.
#templateVar
También podemos acceder al elemento desde el código del componente. Creamos un atributo en el componente de tipo ElementRef. Anotamos ese atributo con @ViewChild(‘refName’).
Composición de componentes
Al cargar la app en el navegador, en el árbol DOM cada componente incluye en su elemento el contenido de la vista.
Comunicación entre un componente padre y un componente hijo
Configuración de propiedades (Padre Hijo)
Vista
<header [title]='appTitle'></header>
Controlador
export class HeaderComponent {
@Input()
private title: string;
}
Envío de eventos (Hijo Padre)
Vista
<header (hidden)='hiddenTitle($event)'></header>
Controlador
export class HeaderComponent {
@Output()
hidden = new EventEmitter<boolean>();
visible = true;
click(){
this.visible = !this.visible;
this.hidden.next(this.visible);
}
}
Invocación de métodos (Padre Hijo)
Compartiendo el mismo servicio (Padre Hijo)
Servicios
Acoplar en el componente la lógica de las peticiones http no es una buena práctica. El componente podría llegar a ser muy complejo y difícil de ampliar / modificar. Es mucho más difícil implementar tests unitarios si el componente tiene muchas responsabilidades. Es mucho mejor modularizar la aplicación en elementos que tengan una única responsabilidad.
A los elementos de la aplicación que no se encargan del interfaz de usuario se les conoce como servicios. Angular 2 ofrece muchos servicios predefinidos. El objeto http se considera un servicio de acceso a APIs REST, pero existen más. El desarrollador puede implementar sus propios servicios en la aplicación.
¿Cómo se implementa un servicio?
Se crea una nueva clase para el servicio
-
Se anota esa clase con @Inyectable
-
Se indica esa clase en la lista de providers del NgModule
-
Se pone como parámetro en el constructor del componente que usa el servicio
@Injectable() export class BooksService { getBooks(title: string){ return [ 'Aprende Java en 2 días', 'Java para torpes', 'Java para expertos' ]; } }
Inyección de dependencias
Es la técnica de solicitar dependencias que sean inyectadas por el framework se denomina inyección de dependencias.
@Component({
selector: 'approot',
templateUrl: './app.component.html'
})
export class AppComponent {
private books: string[] = [];
constructor(private booksService: BooksService){}
search(title: string){
this.books = this.booksService.getBooks(title);
}
}
Es habitual que haya un único objeto de cada servicio en la aplicación.
Router
Las webs SPA (single page application) pueden tener varias pantallas simulando la navegación por diferentes páginas.
En app.routing.ts se define qué componente se muestra para cada URL.
El componente principal de la aplicación (app-root) tiene una parte fija (cabecera, footer) y una parte cuyo contenido depende de la URL (<routeroutlet>).
Existen links especiales para navegar dentro de la aplicación web ([routerLink]).
@Component({
selector: 'approot',
template: `
<h1 class="title">Library</h1>
<routeroutlet></routeroutlet>
`
})
export class AppComponent { }
Configuración de las rutas
const appRoutes = [
{ path: 'book/:id', component: BookDetailComponent, },
{ path: 'books', component: BookListComponent },
{ path: '', redirectTo: 'books', pathMatch: 'full' }
]
Parametro de router
Navegación con router
Publicación
ng build --target=production --environment=prod