Inicio del curso

1

De qu茅 tratar谩 este curso sobre Angular 4

Introducci贸n a Angular 4

2

Versionamiento en Angular

3

驴Qu茅 es Angular? Versiones y ventajas

4

Typescript: qu茅 es

5

Introducci贸n al Proyecto: PlatziSquare!

Setup del Ambiente de Trabajo

6

Herramientas de trabajo y Angular CLI

7

Generaci贸n y estructura de Angular 4

8

RETO: Haz un cambio simple en el proyecto.

Conceptos B谩sicos

9

Para qu茅 nos sirven los M贸dulos y Componentes

10

Tipos de Data Binding y String Interpolation

11

Property Binding

12

Event Binding

13

Two Way Data Binding

14

Directivas en Angular 4 y ngFor

15

Directiva ngIf

16

Instalando librer铆as con NPM (Google Maps)

Directivas

17

Directivas ngStyle y ngClass

18

Directiva ngSwitch

19

Directiva de atributo

20

Host Listeners

21

Host Binders

Angular UI

22

Angular Material y Bootstrap

23

Configurando e implementando Bootstrap en nuestro proyecto

Ruteo

24

Qu茅 hace el router en Angular 4

25

Implementaci贸n de Rutas en el Proyecto

26

Diferencias entre href y routerLink

27

Resaltando el link activo con CSS para indicar visualmente en que componente nos encontramos

28

Par谩metros en Rutas

29

Par谩metros tipo Query

30

Creando una vista de detalle para el proyecto

31

Creando la p谩gina de contacto para PlatziSquare

Servicios

32

Qu茅 son los servicios en Angular 4

33

Creando nuestro propio servicio

34

Configurando Firebase en nuestro proyecto

35

Guardando Records en Firebase

36

Obteniendo records desde Firebase

37

Obteniendo coordenadas usando Geocoding

38

Reto: Crear una vista para editar records

39

Mostrando marcadores en el Mapa de Google

Conexi贸n Remota (Http y Sockets)

40

Funcionamiento de los llamados Http y Sockets

41

Qu茅 es una arquitectura cliente - servidor

42

Enviando llamados tipo POST

43

Enviando llamados tipo GET

44

Formateando respuestas del servidor con el operador map()

45

Manejando errores HTTP

Pipes

46

Utilidad de los Pipes en Angular 4

47

Usando los pipes por defecto de Angular

48

Par谩metros en pipes

49

Creando nuestro propio pipe

Animaciones en Angular

50

Configurando animaciones en nuestro proyecto

51

Transiciones

52

Callbacks

53

Soluci贸n al Reto: A帽adiendo animaciones a nuestra aplicaci贸n

Testing en Angular

54

Introducci贸n a unit tests

55

Configuraci贸n de testing por default

56

Corriendo los tests

57

Creando unit tests para componentes

58

Integraci贸n de Unit Test con Servicios

Autenticaci贸n y Protecci贸n de Rutas

59

C贸mo funcionan los JSON Web Tokens

60

Preparaci贸n de vistas para login y registro

61

Registrando usuarios

62

Loggeando usuarios

63

Protecci贸n de Rutas

64

Autenticaci贸n con redes sociales.

65

Logout

RxJS

66

Qu茅 es RxJS

67

Configurando RxJS en nuestro proyecto

68

Uso de los Observables

69

Implementando un TypeAhead

70

Implementando un TypeAhead 2

71

Soluci贸n al reto autocompletar los campos de direcci贸n usando observables

Publicando nuestro proyecto

72

Publicando en Firebase Hosting

Fin del curso

73

Conclusi贸n 驴Qu茅 aprendimos en el curso?

74

Reto final del curso - realiza un nuevo modulo de PlatziSquare de acuerdo con las historias de usuario

Sesiones en vivo

75

Creando un traser bullet de PlatziSquare

76

Sesi贸n de preguntas y respuestas

77

Release de Angular 5

78

Sesi贸n de preguntas y respuestas

79

Angular Universal

Contenido Bonus

80

Actualizaci贸n de angular, versi贸n 6.0

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Curso de Angular 4

Curso de Angular 4

Eduardo Ibarra

Eduardo Ibarra

Directiva de atributo

19/80
Recursos

Ya hemos usado directivas como ngSwitch, gIf, ngClass, etc, 茅stas son directivas que ya vienen definidas por el framework, en 茅ste v铆deo vamos a crear una directiva propia para resaltar aquellos negocios que te est茅n pagando por publicidad.

Aportes 21

Preguntas 9

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Angular nos permite desarrollar directivas personalizadas. Es necesario manejar diferentes elementos, tales como:

@Directive: Anotaci贸n para identificar un elemento como directiva.

OnInit: Interface que es llamada cuando las propiedades de una directiva son invocadas.

ngOnInit: Funci贸n que es ejecutada al momento de llamar la directiva. Ac谩 se coloca la l贸gica de negocio.

ElementRef: Clase utilizada para hacer referencia al elemento en donde se est谩 implementando la directiva.

Renderer2: Renderiza el elemento cuando se le asigna un estilo.

Input: Tipo de metadata de entrada.

Si usas VSCODE puedes usar el hotkey alt+shift +f y reorganiza el codigo. Super util!

Bueno gente de platzi, aqui explican demasiadas cosas en un video, no se entiende !

Soy yo o esta clase no se entiende absolutamente nada?

Este video fue un poco trivial de entender e implementar. Pero lo pude lograr. Como nota, el tslint me pide cambiar de

selector : '[resaltar]'

a

selector : '[appResaltar]'

seguimos 鈥

mi archivo app.component.html

<ng-container *ngFor=鈥渓et lugar of lugares ; let i = index鈥 [ngSwitch]=鈥渓ugar.cercania鈥>
<!鈥<li *ngIf=鈥減ersona.Edad>=34鈥>{{persona.nombre}}</li>鈥>
<li [ngStyle]="{color: (lugar.active) ? 鈥榖lack鈥 : 鈥榞ray鈥檥" [ngClass]="{numero_par: (i+1) % 2 !== 0}" [resaltar]=鈥渓ugar.plan鈥>
{{lugar.nombre}} -
<span *ngSwitchCase=鈥1鈥 [ngStyle]="{color: 鈥榞reen鈥檥 鈥>Muy Cercano</span>
<span *ngSwitchCase=鈥2鈥 [ngStyle]=鈥漿color: 鈥榖lack鈥檥 鈥>Cercano</span>
<span *ngSwitchCase=鈥3鈥 [ngStyle]=鈥漿color: 鈥榬ed鈥檥 ">Lejano</span>
</li>
</ng-container>

mi archivo app.component.ts

lugares:any=[
{plan: 鈥榩agado鈥 , cercania: 1, distancia: 1 , active: true , nombre:鈥楩loreria de Gardenia鈥檥,
{plan: 鈥榞ratuito鈥 , cercania: 1, distancia: 1.8 , active: true , nombre:鈥楧onas la pasadita鈥檥,
{plan: 鈥榞ratuito鈥 , cercania: 2, distancia: 5 , active: true , nombre:鈥榁eterinaria Huellitas Felices鈥檥,
{plan: 鈥榞ratuito鈥 , cercania: 3, distancia: 10 , active: false , nombre:鈥楽ushi Suhiroll鈥檥,
{plan: 鈥榩agado鈥 , cercania: 3, distancia: 35 , active: true , nombre:鈥楬otel la Gracia鈥檥,
{plan: 鈥榞ratuito鈥 , cercania: 3, distancia: 120 , active: false , nombre:鈥榋apateria el Clavo鈥檥
];

resaltar.directive.ts

import { Directive, OnInit, ElementRef, Renderer2, Input } from 鈥楡angular/core鈥;
@Directive({
selector : 鈥榌resaltar]鈥
})
export class ResaltarDirective implements OnInit{
constructor(private elRef: ElementRef, private renderer: Renderer2){}
@Input(鈥榬esaltar鈥) plan : string = 鈥樷;
ngOnInit(){
if(this.plan === 鈥榩agado鈥){
this.renderer.setStyle(this.elRef.nativeElement, 鈥榖ackground-color鈥, 鈥榶ellow鈥);
this.renderer.setStyle(this.elRef.nativeElement, 鈥榝ont-weight鈥, 鈥榖old鈥);
}
}
}

Pregunta. 驴Por qu茅 es necesario que los objetos ElementRef y Renderer2 sean enviados como p谩rametros del constructor en vez de ponerlos como atributos de la clase?
Es decir por qu茅 esto:

constructor(private refer: ElementRef, private render: Renderer2) {}

En vez de esto:

private refer: ElementRef
private render: Renderer2
constructor() {}

Investigando m谩s acerca de las dependencias OnInit, Renderer2, Input, ElementRef y Directive

Angular nos permite crear solo directivas de atributos?
como puedo crear directivas estructurales?

buenas clases

Directiva de atributo
Excelente! me sirvio de mucho!! Gracias equipo !

驴Hey profe c贸mo hace para poner multi selector en phpstorm? lo he buscado pero no lo he encontrado

Dejenmen ver si entend铆, en la directiva inyectamos 2 m贸dulos con los cuales voy a agregar estilos llamando al elemento nativo con elRef, y ese elemento lo atrapo en una variable de tipo Input (que seria el elemento nativo) llamada plan? ** 驴Correcto? **

驴Cual es la diferencia entre hacer acciones en el ngOnInit(){} o en el constructor(){} Donde es lo ideal? Es lo mismo? Cual es la mala practica? Gracias

what鈥檚 the difference bewteen including it on the imports array and declarations array?

Hasta ahora el curso en mi opini贸n personal esta bien explicado en cuanto a Angular, creo que prefiero la manera en como lo hace React aun as铆 quise tomar este curso y tomare el ultimo de Angular 6 para ver que tal esta, aun as铆 siento que tienes que hacer mas cosas aqu铆, que con lo que har铆as en React, aun no puedo hacer un juicio definitivo, hasta que lo termine completo. saludos.

Ejecuto lo siguiente en Node.js y me crea el archivo de la directiva.
ng g d directives/resaltar

Por ac谩 dejo mi c贸digo:
highlight.directive.ts

import { Directive, ElementRef, OnInit, Renderer2, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective implements OnInit {

  @Input('appHighlight') plan: string = ''

  constructor(private refer: ElementRef, private render: Renderer2) {}

  ngOnInit(): void {
    if (this.plan === 'bought') {
      this.render.setStyle(this.refer.nativeElement, 'background-color', '#7fffd4')
      this.render.setStyle(this.refer.nativeElement, 'color', '#002a00')
    }
  }

}

app.component.ts

import { Component, OnInit } from '@angular/core';
import { environment } from 'src/environments/environment';
import * as mapboxgl from "mapbox-gl";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})

export class AppComponent implements OnInit {

  title: string = 'Angular';
  name: string = '';
  lastName: string = '';
  notReady: boolean = true;
  map: mapboxgl.Map;
  coordinates: any;
  places: any = [
    { plan: 'bought', color: '#00ff00', closeness: 1, distance: 3, active: true, name: "Florer铆a la Gardenia" },
    { plan: 'free', color: '#360000', closeness: 3, distance: 50, active: true, name: "Donas Vida Dulce" },
    { plan: 'free', color: '#00ff00', closeness: 1, distance: 8, active: true, name: "Veterinaria Huellitas" },
    { plan: 'bought', color: '#360000', closeness: 3, distance: 30, active: true, name: "Sushi Roll" },
    { plan: 'free', color: '#baf73c', closeness: 2, distance: 10, active: false, name: "Hotel la Gracia" },
    { plan: 'free', color: '#baf73c', closeness: 2, distance: 20, active: false, name: "Zapater铆a Clavo" },
  ];

  ngOnInit():void {
    mapboxgl.accessToken = environment.mapboxKey;
    this.map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v11',
      center: [-74.0700526, 4.6489681],
      zoom: 10
    });
    this.createMarker(-74.0700526, 4.6489681)
  }

  createMarker(lng: number, lat: number): void {
    const marker = new mapboxgl.Marker({
      draggable: true
    })
    .setLngLat([lng, lat])
    .addTo(this.map)

    marker.on('drag', () => {
      this.coordinates = marker.getLngLat()
    })
  }

  check():void {
    if (this.name === '' || this.lastName === '') {
      this.notReady = true;
    } else {
      this.notReady = false;
    }
  }

  hello():void {
    alert(`Welcome to this App ${this.name} ${this.lastName}`);
  }

}

app.component.html

<div class="textcenter">
  <h3>{{ title }} app is running!</h3>
  Tu nombre es {{ name }} {{ lastName }} <br />
  <input
    type="text"
    placeholder="Nombre"
    (keyup)="check()"
    [(ngModel)]="name"
  />
  <input
    type="text"
    placeholder="Apellido"
    (keyup)="check()"
    [(ngModel)]="lastName"
  />
  <button [disabled]="notReady" (click)="hello()">Hi</button>
</div>
<br />
<span class="textmarginleft">{{ coordinates }}</span>
<br />
<div class="inline" id="map"></div>
<div class="inline" id="list">
  <ul>
    <ng-container *ngFor="let place of places; let i = index">
      <li *ngIf="place.active" [ngClass]="{ evennumber: (i + 1) % 2 === 0 }">
        {{ place.name }}
      </li>
    </ng-container>
  </ul>
  <ul>
    <ng-container *ngFor="let place of places; let i = index">
      <li
        [ngStyle]="{ 'text-decoration': place.active ? '' : 'line-through' }"
        [ngSwitch]="place.closeness"
        [appHighlight]="place.plan"
      >
        {{ place.name }} -
        <span *ngSwitchCase="1" [ngStyle]="{ 'color': place.color }">Cercano</span>
        <span *ngSwitchCase="2" [ngStyle]="{ 'color': place.color }">Intermedio</span>
        <span *ngSwitchCase="3" [ngStyle]="{ 'color': place.color }">Lejano</span>
      </li>
    </ng-container>
  </ul>
</div>

FYI

import { Directive, OnInit, ElementRef, Renderer2, Input } from "@angular/core";

@Directive({
    selector: '[resaltar]'
})

export class ResaltarDirective implements OnInit{
    // ElementRef -> permite crear una referencia html (nodo html)
    // Renderer2 -> enfocado a atributos css del nodo html
    constructor(private elRef:ElementRef,private renderer:Renderer2){}
    
    @Input('resaltar') plan:string = '';

    ngOnInit(){
        if(this.plan === 'pagado'){
            // setStyle => Elemento Nativo, atributo css , valor css
            this.renderer.setStyle(this.elRef.nativeElement,'background-color','yellow');
            this.renderer.setStyle(this.elRef.nativeElement,'font-weight','bold');
        }
    }
}
<div>
    <button type="button" (click) = "changeTitle( 'Nuevo nombre' )" > Click me! </button>
    <br><hr/><br>
    <input type="text" placeholder="Ingrese nombre" [(ngModel)] = "firstName" />
    <br>
    <input type="text" placeholder="Ingrese Apellido" [(ngModel)] = "lastName" />
    <br>
    <input type="text" placeholder="Ingrese Edad" [(ngModel)] = "age" />
    <br>
    <button type="button" (click) = "addPerson()" > Agregar! </button>
    <br>
    <span> {{message}} </span>
    <br>
    <div> Lista de activos </div>
    <ul>
      <ng-container *ngFor="let person of persons">
          <li *ngIf="person.active && person.age > 17"> 
            {{person.firstName}} - {{person.lastName}} - {{person.age}} 
            <span (click) = "deletePerson(person.id)" > x </span>
          </li>
      </ng-container>
    </ul>

    <div> Lista de personas </div>
    <ul>
      <ng-container *ngFor="let person of persons; let i = index">
          <li 
            [ngStyle] = "{ color: (person.active) ? 'black' : 'grey' }" 
            [ngClass] = "{ impar:(i+1) % 2 !== 0, par:(i+1) % 2 === 0 }"
            [ngSwitch] = "person.active"
            [shade] = "person.active"> 
              {{person.firstName}} - {{person.lastName}} - {{person.age}} 
              <span *ngSwitchCase = "true" [ngStyle] = "{color:'green'}"> Activo</span>
              <span *ngSwitchCase = "false" [ngStyle] = "{color:'red'}"> Borrado </span>
              <span *ngIf = "person.active" (click) = "deletePerson(person.id)" > x </span>
          </li>
      </ng-container>
    </ul>
  </div>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'berckmanCurso';
  firstName:string = "";
  lastName:string = "";
  age:numbre = 0;
  message:string = "";
  count = 1;

  persons:Array<Object> = [
    {id: 1, firstName: "Newman" , lastName: "Fajardo", active:true, age: 25 }
  ];
 
  changeTitle(title){
    this.title = title;
  }

  addPerson(){
    this.count++;
    this.persons.push({
      id: this.count,
      firstName: this.firstName , 
      lastName: this.lastName,
      age: this.age,
      active:true
    });
    this.message = "Persona guardada";

    setTimeout( () => { this.message = ""; } , 2000 );
  }

  deletePerson(id){
    this.persons = this.persons.map( person => {
      if (person.id == id) {
        person.active = false;
      }
      return person;
    });
  }
}
import { Directive, OnInit, ElementRef, Renderer2, Input } from "@angular/core";

@Directive({
    selector: '[shade]'
})

export class ShadeDirective implements OnInit{
    @Input("shade") validated: boolean = false;
    constructor(private elRef: ElementRef , private renderer: Renderer2){}

    ngOnInit(){
        this.validatedActive();
    }

    ngOnChanges(){
        this.validatedActive();
    }

    validatedActive(){
        if(this.validated){
            this.renderer.setStyle(this.elRef.nativeElement , 'background-color' , 'indigo');
            this.renderer.setStyle(this.elRef.nativeElement , 'font-weight' , 'bold');
        }  
        else{
            if(this.elRef.nativeElement.className == "par"){
                this.renderer.setStyle(this.elRef.nativeElement , 'background-color' , 'chocolate');
                this.renderer.setStyle(this.elRef.nativeElement , 'font-weight' , 'normal');
            }
            else{
                this.renderer.setStyle(this.elRef.nativeElement , 'background-color' , 'honeydew');
                this.renderer.setStyle(this.elRef.nativeElement , 'font-weight' , 'normal');
            }
        }
    }
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import {FormsModule} from '@angular/forms';
import { ShadeDirective } from './directives/shade.directive';

@NgModule({
  declarations: [
    AppComponent,
    ShadeDirective
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

En el ejemplo, la condici贸n esta dentro de la directiva, como puedo hacer que siempre se aplique la directiva, pero la l贸gica de la condici贸n este del lado del html, como se aplic贸 para para el ngStyle y el class en el ejemplo?