Angular

Ejemplos WebApps y SPA

Ordenador usuario

Servidor facebook

== DAME EL index.HTML =>

<= Toma el index.html ==

== El usuario navega a categories.html =>

Single Page Application 

Se refresca la pantalla

NAVEGO a categorias.html

Me autosirvo el template

Me renderizo una cosa nueva

Dame todos los ficheros

Toma los scripts y los css

ng new project

Carpeta src 

Esto es lo importante

Alternativa

EN ANGULAR2+

Nos encontraremos que cada página o componente se compone de :

un fichero .html

un fichero .css

un fichero .ts

LA VISTA

 

EL MAQUILLAJE

 

LA LOGICA

¿Cómo arrancamos nuestro proyecto?

ng serve

¡¡ {{ magic }} !! 

{{ entre llave y llave }}

puedo ejecutar funciones

<p> El numero PI = {{ getPi() }}</p>
<p>Radio de un círculo : 3cm </p>
<p>Área del círculo {{ (getPi() * radio*radio) }}</p>
export class AppComponent {
  radio : number = 3;
  
  getPi(): number {
    return 3.14159265359;
  }
}

[ ]  

Realmente cuando usamos unos corchetes, le estamos indicando a angular que ese atributo tiene a la derecha del igual una expression a evaluar

salvo en ngmodel

[binding]  

[ ]  

Para este ejemplo, la diferencia entre src y alt

  • [src]: espera una variable

  • alt: espera un string
     

<img [src]="url" alt="foto">

[bindear]


<img 
    [src]="imagen.fuente"

    [alt]="imagen.alt"

    [title]="imagen.title"
/>

<a [href]="nuevaRuta"> pincha aquí </a>
//ts

imagen = {
  fuente : "https://via.placeholder.com/600/771796",
  alt : 'imagen',
  title : 'cuadrado random'
}

[cualquierAttr]


<img 
    [src]="image.link"

    [alt]="image.alt"

    [title]="image.title"
/>

<a [href]="nuevaRuta"> pincha aquí </a>

<div [class]="clases" [id]="id"> Divs</div>

[ngStyle]  

[ngStyle]="{ 'color' :  color}"  

[style.color]="color"  

[class.pintame]="condicion"  

//css
.pintame {
  color: red;
}

[ngClass]="{ 'pintame' :  condicion}"  

<p>Num : {{num}}</p>
<button (click)="increment(1)">Sumar 1</button>
<button (click)="increment(2)">Sumar 2</button>

(click)="increment(2)"

(click)="increment(2)"

(eventos)

( )

¡¡¡Resumen!!!

[ ]

Fichero.html

Fichero.ts

Fichero.html

Fichero.ts

[( NGMODEL )]

Recoger valores de un input

<p> El numero PI = {{ getPi() }}</p>
<input type="number" placeholder="Radio" [(ngModel)]="radio" />
<p>Área del círculo {{ (getPi() * radio*radio) }}</p>
export class AppComponent {
  radio : number = 3;
  
  getPi(): number {
    return 3.14159265359;
  }
}

¿Ficheros .ts?

TypeScript is a typed superset of JavaScript

that compiles to plain JavaScript

A superset

Javascript

  • Tipado débil.
  • Autocompletado ahí ahí.
  • No avisa de errores.
  • Navegadores viejos.

Typescript

  • Tipado "fuerte"
    Autocompletado si...
  • Avisa de problemas
  • Código TS ---> JS ES6

typescript

  • Tipado de variables y de parámetros
  • Orientado a clases
  • Importar exportar clases
  • Webpack
  • Un largo etc 

 

Aspectos Signicativos

Valores de distinto tipo

Atributos y mtodos incorrectos

Variables no declaradas

Varios valores

Error

Tipado

function createUser(email, name, age){ ...}

Javascript

function createUser(email: string, name: string, age: number){ ...
}

Typescript

Typescript en Angular

//Se declara de la siguiente forma.

export class AppComponent {
  public name: string = 'Manolín';

  constructor () {
    //El constructor es el que primero se 
    //inicializa al iniciar la clase.
    alert(`${this.getHello()} ${this.name}`)
  }

// Para declarar una función
  public getHello() : string {
    return 'Hello';
  }
}

this this this

this this this

this this this

this this this

this this this

 <ul>
    <li *ngFor="let word of stack">{{word}}</li>
 </ul>
export class AppComponent {
  stack = ['Esto', 'es', 'un', 'array'];

  addTask (task) {
    this.stack.push(task);
  }
}

*ngFor="let word of stack"

Primera iteración: word = stack[0]

Segunda iteración: word = stack[1]

Bucles con Angular (*ngFor)

¿y si tenemos un array de objetos?

export class AppComponent {

  public people: any[] = [];
  public person: any = {
    name: '',
    age: null,
    type: ''
  };

  constructor() {
    this.people = [
      {
        name: 'Pedro',
        age: 15,
        type: 'Young'
      }, {
        name: 'Borja',
        age: 27,
        type: 'Adult'
      }, {
        name: 'Yunior',
        age: 50,
        type: 'Old'
      }
    ]
  }
}
<div *ngIf="people.length > 0">
  <div *ngFor="let person of people">
    <h3>{{person.name}}</h3>
    <small>Edad: {{person.age}}</small>
    <br>
    <small>Clase: {{person.type}}</small>
  </div>
</div>

<div *ngIf="people.length == 0">
  <h2>No hay ningúna entrada!</h2>
</div>

¿y si tenemos un array de objetos?

export class AppComponent {

  public people: any[] = [];
  public person: any = {
    name: '',
    age: null,
    type: ''
  };

  constructor() {
    this.people = [
      {
        name: 'Pedro',
        age: 15,
        type: 'Young'
      }, {
        name: 'Borja',
        age: 27,
        type: 'Adult'
      }, {
        name: 'Yunior',
        age: 50,
        type: 'Old'
      }
    ]
  }
}

[hidden]="condicion"

Si la condición da true se ocultará el elemento, si no se mostrará en la pantalla 

<div *ngFor="let person of people" class="card" 
	[ngClass]="{'underage': person.age < 18}" 
	[hidden]="person.age > 49">
  
</div>

se muestran todos, menos......? (Pregunta)

Condiciones con Angular (*ngIf)

<div *ngIf="stack.length > 0">
  <ul>
    <li *ngFor="let task of stack">{{task}}</li>
  </ul>
</div>

<div *ngIf="stack.length == 0">
  <h2>No hay ningúna entrada!</h2>
</div>
export class AppComponent {
  newTask = '';
  stack = [];

  addTask (task) {
    this.stack.push(task);
    this.newTask = '';
  }
}

*ngIf = "condición"

Aunque no tenga los [], el ngIf espera una condición booleana.
Que le diga si se muestra o no se muestra

*ngIf="condicion"

Si la condición da true se mostrará en el DOM, si no...,
SE BORRARÁ DEL DOM

*ngIf vs [hidden]

*ngIf vs [hidden]

<button 
      *ngIf="hideCompleted" 
      (click)="hideCompleted = !hideCompleted"
      >Mostrar completados
</button>
<button 
      *ngIf="!hideCompleted" 
      (click)="hideCompleted = !hideCompleted"
      >Ocultar completados
</button>
<li 
  [hidden]="hideCompleted && item.completed" 
  *ngFor="let item of items" 
  [ngClass]="{'completed' : item.completed}">
    <span (click)="completeMe(item.title)">{{item.title}}</span>
    <button (click)="deleteMe(item.title)"> Borrar</button>
</li>

desaparecerá

se hace invisible

Practicando en directo !

Hagamos una aplicación de gestión de tareas que cumpla con:

 

  • El usuario podrá rellenar un input y darle a guardar para crear una nueva tarea
  • El usuario debería de poder borrar una tarea.
  • El usuario puede marcar como completada una tarea.

Angular Components

Angular Components

Pero primero un repaso muy rápido de lo anterior.

Angular Components

Un componente de angular es como una pieza de Lego. Creas un cuerpo principal y vas añadiendo piezas para conformar una figura.

Esto hace que el programa sea más escalable y que cada pieza que compone al programa sea más independiente, evitando romper el resto del programa.

Angular Components

Ejemplos WebApps y SPA

Angular Components

Ejemplos WebApps y SPA

Angular Components

Ejemplos WebApps y SPA

Angular Components

Angular Components

Crear un componente de angular

ng generate component nombre_del_componente

Angular Components

ng generate component nombre_del_componente

Carpeta components

ng g component components/nombre_del_componente

Angular Components

¿Qué se genera?

Veamos detalladamente el decorador @component.

Angular Components

Ejemplo

appComponent.html

menu.component.html

Angular Components

@Component({
  selector: 'app-menu', // ¿Y esto? Magia (Lo explico un poquito más adelante),
  templateUrl: './menu.component.html', //EL html asociado este componente.
  styleUrls: ['./menu.component.css'] //El estilo asociado a este componente
})

menu.component.ts

¿No te recuerda al appComponent.ts? Tienen la misma estructura 😊

Angular Components

@Component({
  selector: 'app-menu', // ¿Y esto? Magia (Lo explico un poquito más adelante),
  templateUrl: './menu.component.html', //EL html asociado este componente.
  styleUrls: ['./menu.component.css'] //El estilo asociado a este componente
})

menu.component.ts

  • El css estará encapsulado para cada componente, esto significa que todo lo que quieras maquetar de dicho componente lo debes hacer dentro su fichero css
     
  • Cada componente tienen su archivo de estilo.

Angular Components

@Component({
  selector: 'app-menu', // ¿Y esto? Magia (Lo explico un poquito más adelante),
  templateUrl: './menu.component.html', //EL html asociado este componente.
  styleUrls: ['./menu.component.css'] //El estilo asociado a este componente
})

menu.component.ts

  • Si intentas maquetar desde el componente menu algo del  app.component...​

¿No se ve verdad?

Más info

Angular Components

@Component({
  selector: 'app-menu', // ¿Y esto? Magia (Lo explico un poquito más adelante),
  templateUrl: './menu.component.html', //EL html asociado este componente.
  styleUrls: ['./menu.component.css'] //El estilo asociado a este componente
})

menu.component.ts

  • El css tiene  scope, eso significa que solo le aplicará los cambios a si mismo.

 

  • Es decir, solo el menu.component.css podrá cambiar los estilos del menu.component.html

Más info

Angular Components

Para poder usar un componente, debemos nombrar en el HTML con el nombre del selector

@Component({
  selector: 'app-menu', // ¿Y esto? Magia,
  templateUrl: './menu.component.html', //EL html asociado este componente.
  styleUrls: ['./menu.component.css'] //El estilo asociado a este componente
})
//export class MenuComponent...

Angular Components

Para verlo mejor, descarga esta extensión de chrome.
Se podrá usar solo si estas en localhost.

Angular Components

¿Que más generó el ng component?

  • Al generar el componente a través del CLI, nos facilita algunas cosas y hace otras por nosotros.
     
  • Este directamente importa al module el componente menú.
     
  • Todos los componentes deben estar declarados ahí.

Angular Components

En el app.modules. Comenta la linea 6 (como está en la imagen de abajo) y borra lo que está en el cuadrado rojo en la misma imagen.

¿Que sucede?

Angular Components

¿Qué pasa si no lo declaro en el app.module?

Angular Components

¿Qué pasa si no lo declaro en el app.module?

El app.component.html no reconoce la tag <app-menu> del selector del componente

Angular Components

¿Qué pasa si no lo declaro en el app.module?

El app.component.html no reconoce la tag <app-menu> del selector del componente

Angular Components

HORA DE TRABAJAR!

<gallery>

<photo></photo>

<photo></photo>

<photo></photo>

  • Consigue realizar la imagen de la izquierda, usando componentes.
     
  • Crea una componente por cada elemento que  ves en la imagen.
    ejemplo.
    ng generate component gallery

  •  

</gallery>

app.component.html

 

Angular Components

HORA DE TRABAJAR!

<header></header>

<aside></aside>

<Gallery></Gallery>

<photo></photo>

<photo></photo>

<photo></photo>

  • Consigue realizar la imagen de la izquierda, usando componentes.
     
  • Crea una componente por cada elemento que  ves en la imagen.
    ejemplo.
    ng generate component header

  • Usa css para conseguir el estilo que se ve en la imagen. O algo mejor ;)

Inputs & Outputs

ANGULAR
COMPONENT

INPUTS

OUTPUTS

Inputs & Outputs

En algunos casos, un componente puede haber recibido o realizado un evento y quiere comunicar con su padre dicho evento. Para esto se usa los @Output()

Detallemos cada uno de ellos

Un componente puede recibir valores de su padre, para esto se usarán los @Input()

Inputs 

Los componentes para que estos sean más independientes y que cada uno realice su función, se les pueden pasar datos de entrada (@Input()).

Para explicarlo mejor, usando como ejemplo el ejercicio de  ayer: 

  • <app-menu>, solo hace cosas del menú.
     
  • <app-gallery>, solo hace cosas con las fotos.

 

  • <app-photo>, solo se encargará de representar una foto

¿Cómo se usa esto en Angular?

Inputs 

Si queremos enviar un input a un componente, debemos asegurarnos primero que se importe Input

Si queremos enviar un texto desde app component al  menu.component.

Declaramos una variable title y delante le añadimos @Input() para decirle a angular que title es un parámetro de entrada.

Inputs 

¿Cómo enviamos el valor?

¿Pero también podemos pasar variables? 🤔

Inputs 

Si, también podemos pasar una variable desde el app.component

Inputs 

Si, también podemos pasar una variable desde el app.component

Inputs 

¿Y si queremos pasar más inputs?

El padre

El hijo (componente)

Inputs 

¿Y si queremos pasar más inputs?

resultado

Puedes pasar tantos como quieras o sean necesarios

Live coding

¡ Ejercicio para practicarlo !

¿Y si queremos pasar un array?

Intenta hacerlo tú. Usa el team component para conseguir que se muestren todos los elementos del array people

La base para resolver el ejercicio:

https://stackblitz.com/edit/clm-ed2-inputs-team-example

Inputs 

Vamos a ir un paso más allá

Creemos el elemento TeamMember que recibirá un solo person para dibujarlo en la pantalla.

Live coding ! ¿Vamos más allá?

Outputs

Estos componentes pueden realizar acciones o eventos que pueden ser realizados por el padre del mismo. En este caso son considerados datos de salida (@Output())

Si queremos activar un evento del padre, podremos usar el @output conjunto a un emitidor de evento (EventEmiter).

¿Cómo se usa esto en Angular?

Si queremos enviar un output y emitir un evento desde un componente hijo a un componente padre, debemos asegurarnos primero que se importe Output y el EventEmitter

Para avisar de un evento desde menu component a app.component.

Outputs

  • Al declarar un output de esta forma, estás declarando un nuevo emitidor de eventos.
  • Este avisará al componente padre de que se ha activado un evento.

¿Como usamos ese emitidor y como le asignamos un evento?

Supongamos que tenemos un boton en el componente menú y que queremos notificar al app component, que se ha pulsado ese botón haciendo que el app component muestre una alert.

Outputs

En el menu component ts, declaramos el metodo asociado al click.

En el usamos la variable antes declarada y le decimos que queremos emitir ese valor.

¿Cómo lo recibimos en el app component?

Outputs

El mismo nombre que hemos usado para declarar los outputs lo usaremos en el app component. Debido a que es un evento los pondremos entre parentesis. 

<menu (notifyMyFather)="whatMyChildSay($event)"></menu>
  • Creamos una función que esté asociada al evento emitido en el componente menú.
     
  • Esta función se ejecutará, sí en el componente hijo emite un evento.
     
  • Puedes pasar variables desde el componente hijo al padre.
     
  • En $event estará el parámetro enviado desde menú.

menu.component.ts

app.component.html

Resultado

Outputs

Live coding

Ejercicio ! Haz algo como lo siguiente

Outputs. Te toca a ti.

Outputs

¿ y si juntamos lo que hemos aprendido en la semana?

  • ngIf
  • ngFor
  • Components
  • Inputs
  • Outputs

Ejercicio

app.component

shopping-list.component

item.component

cart.component

Ejercicio

  • Crea un shopping-list.component.
    Este tendrá 3 inputs:
                    - Producto : string
                    - Cantidad : number
                    - Precio : number (números enteros y positivos)
    y un botón "add carrito". También usará al componente cart y le mantendrá el array de artículos introducidos guardado
     
  • Crea un cart.component, aquí se irán mostrando los productos recibidos por @input en forma de lista (*ngFor) 

 

  • Crea un item.component, que recibe un objeto de tipo producto y lo renderiza en la pantalla. Además muestra un botón de eliminar
     
  • Finalmente, desde shopping-list.component se mostrará la suma de los productos comprados y habrá un botón de "pagar"