Angular SPA

Autor: Gao Fecha: 2019-05-03
Angular SPA

Angular

Introducción a Angular

Angular es un framework para desarrollo SPA, permite extender el HTML con etiquetas propias.

Angular-CLI

Angular CLI

Proyecto

Angular Project Folder

  • 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

Angular Project File

  • 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.

Componente

Import

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.

Event

Sintaxis de los templates

Template Sintaxis

Data Binding

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

CSS de componente

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’).

Element Reference

Composición de componentes

Component Tree

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: 'app­root',
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 (<router­outlet>).

Existen links especiales para navegar dentro de la aplicación web ([routerLink]).

    @Component({
    selector: 'app­root',
    template: `
        <h1 class="title">Library</h1>
        <router­outlet></router­outlet>
    `
    })
    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

Router Param

Router Navegation

Publicación

    ng build --target=production --environment=prod