viernes, 11 de septiembre de 2020

Comunicación entre componentes

Comunicación entre componentes

Tipos de comunicación entre componentes:

  • Padres a hijos con @Input.
  • Hijos a padres con @Output.
  • Mediante servicios.

Comunicación entre componentes padres a hijos con @Input

 
 

 


 

Vamos a pasar el nombre, el apellido y la dirección de una clase padre a una clase hijo usando el decorador @Input ().

Para ello creamos dos componentes llamados padre e hijo:

  • ng generate component padre
  • ng generate component hijo

En la plantilla principal del component hacemos que el padre sea hijo del componente principal de la aplicación:

app.component.html:

<app-padre></app-padre>

Definición del padre:

En la clase del componente padre creamos las variables nombre, apellido y dirección con sus correspondientes valores.

padre.component.ts:

import { Component, OnInit } from '@angular/core';

@Component({

  selector: 'app-padre',

  templateUrl: './padre.component.html',

  styleUrls: ['./padre.component.css']

})

export class PadreComponent implements OnInit {

    nombre = 'Juan';

    apellido = 'Garcia';

    direccion = 'C/la oca';

  constructor() { }

  ngOnInit() {

  }

}

En la plantilla del componente padre vamos a vincular cada propiedad con los valores de las variables definidas en el modulo del componente.

padre.component.html:

<h1>Mi formulario</h1>  

<app-hijo

        [nombre]="this.nombre"

        [apellido]="this.apellido"   

        [direccion]="this.direccion"

</app-hijo>


Definición del hijo:

Importamos el decorador Input, que está en "@angular/core":

import { Component, OnInit, Input } from '@angular/core';

Dentro del componente hijo en el decorador @Input, declaramos las propiedades definidas en la plantilla del padre.

hijo.component.ts:

import { Component, OnInit, Input } from '@angular/core';

@Component({

  selector: 'app-hijo',

  templateUrl: './hijo.component.html',

  styleUrls: ['./hijo.component.css']

})

export class HijoComponent implements OnInit {

  @Input() nombre: string;

  @Input() apellido: string;

  @Input() direccion: string;

  constructor() {

   }

  ngOnInit() {

  }

}


La plantilla del componente hijo: 

A traves del decorador @Input se renderizan los valores de la propiedad en la plantilla del del hijo.

<p>

    Nombre: {{nombre}}

    <br>

    Apellido: {{apellido}}

    <br>

    direccion: {{direccion}}

    <br>    

</p>

 


Comunicación entre componentes hijos a padres con @Output

 


 

Vamos a pasar un dato de una clase hijo a una clase padre mediante un evento.

Para ello creamos dos componentes llamados padre e hijo:

  • ng generate component padre
  • ng generate component hijo

El componente hijo va a generar un evento hacia el padre, para avisarle de un suceso.
El componente padre va a capturar el evento del hijo y lo va a renderizar.

 

Vamos a usar el decorador @Output () en el componente hijo que va emitir el evento hacia el padre donde vamos a usar una propiedad de EventEmitter.

Definición del hijo

hijo.component.ts:

import { Component, OnInit, Output, EventEmitter} from '@angular/core';

@Component({

  selector: 'app-hijo',

  templateUrl: './hijo.component.html',

  styleUrls: ['./hijo.component.css']

})

export class HijoComponent implements OnInit {

  @Output () enviarPadre = new EventEmitter<string>();

  constructor() {

 

   }

  ngOnInit() {

  }

pulsar(value: string) {

  this.enviarPadre.emit(value);

}

}

hijo.component.html:

<button (click)="pulsar('Boton pulsado')">Pulsar</button>

 

Definicion del padre:

padre.component.ts:

import { Component, OnInit } from '@angular/core';

@Component({

  selector: 'app-padre',

  templateUrl: './padre.component.html',

  styleUrls: ['./padre.component.css']

})

export class PadreComponent implements OnInit {

   valor: string;

   constructor() {

 

   }

  ngOnInit() {

   }

   mostrarDato(value: string) {

    this.valor = value;

   }

}

padre.component.html:

<p>Componente Padre</p>

<app-hijo (enviarPadre)= mostrarDato($event)></app-hijo>

<br>

{{this.valor}} 

Mediante servicios

Creamos un servicio utilizando el siguiente comando:

ng g service myservice

 

En el imports de app.module.ts:

  •  Importamos el servicio
import { MyserviceService } from './myservice.service'
  • Lo insertamos en el providers:
providers: [MyserviceService]

Dentro de MyserviceService:

myService.sevice.ts:

import { Injectable } from '@angular/core';

@Injectable({

  providedIn: 'root'

})

export class MyserviceService {

  nombre: string;

  constructor() { }

  setNombre(no: string) {

    this.nombre = no;

  }

  getNombre() {

    return this.nombre;

  }

}

 

Creamos un atributo llamado nombre con sus get y set correspondientes.

Después creamos dos componentes:

ng generate component uno
ng generate component dos


En cada componente inyectamos el servicio creado en el constructor
 

miServicio: MyserviceService;

  constructor(mi: MyserviceService) {

    this.miServicio = mi;

  }

 

El componente uno le va a pasar el valor ‘Juan’ al método set del servicio y el  componente 2 lo va a obtener del método get del servicio y lo va a renderizar:

uno.component.ts:

import { Component, OnInit } from '@angular/core';

import { MyserviceService } from '../myservice.service';

@Component({

  selector: 'app-uno',

  templateUrl: './uno.component.html',

  styleUrls: ['./uno.component.css']

})

 

export class UnoComponent implements OnInit {

  miServicio: MyserviceService;

  constructor(mi: MyserviceService) {

    this.miServicio = mi;

  }

  ngOnInit() {

    this.miServicio.setNombre('Pedro');

  }

}

dos.component.ts:

import { Component, OnInit } from '@angular/core';

import { MyserviceService } from '../myservice.service';

@Component({

  selector: 'app-dos',

  templateUrl: './dos.component.html',

  styleUrls: ['./dos.component.css']

})

 

export class DosComponent implements OnInit {

  miServicio: MyserviceService;

  miNombre: string;

  constructor(mi: MyserviceService) {

    this.miServicio = mi;

  }

  ngOnInit() {

    this.miNombre = this.miServicio.getNombre();

  }

}

dos.component.html:

<p>{{this.miNombre}}</p>

 

 

 

martes, 8 de septiembre de 2020

Formularios en Angular

Formularios en Angular

Tipos de formularios     

  • Formularios basados en plantillas (Template driven forms).
  • Formularios reactivos (Reactive form). 

Formularios basados en plantillas

Son los mas usados en AngularJS y son los mas faciles donde tendremos que implementar menos codigo en la clase, la configuracion la vamos a hacer mediante directivas, donde sus formularios tienen mas dificultad. 

Vamos a usar el enlace de datos bidireccional Two-way Data Binding:

[(ngModel)]="model.property"

Para ello importamos en app.module.ts la siguiente libreria;

import { FormsModule } from '@angular/forms';

Y lo ponemos en la seccion de imports de app @NgModule 

app.component.ts:

import { Component, OnInit } from '@angular/core';

@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css']

})

export class AppComponent{

 titulo = 'Bienvenido a angular';

 constructor() {

  }

  persona = {

    dni: '',

    nombre: '',

    primerApellido: '',

    segundoApellido: '',

};

enviar(event: any) {

  console.log(this.persona.dni);

  console.log(this.persona.nombre);

  console.log(this.persona.primerApellido);

  console.log(this.persona.segundoApellido);

}

}

app.component.html:

<p>persona1 works!</p>

<form>

    <br>

    <p>Dni: <input type="text" [(ngModel)]="persona.dni" name="dni"></p>

    <p>Nombre: <input type="text" [(ngModel)]="persona.nombre" name="nombre"></p>

    <p>PrimerApellido :<input type="text" [(ngModel)]="persona.primerApellido" name="primerApellido"></p>

    <p>SegundoApellido :<input type="text" [(ngModel)]="persona.segundoApellido" name="segundoApellido"></p>

    <input type="submit" (click)="enviar($event)">

</form>

<p>{{this.persona.dni}}</p>

<p>{{this.persona.nombre}}</p>

<p>{{this.persona.primerApellido}}</p>

<p>{{this.persona.segundoApellido}}</p>

 

Formularios reactivos

En los formularios reactivos podemos manejar las entradas de los datos de los formularios que cambian en el tiempo, donde en cada cambio del formulario se produce un nuevo estado.

Para usarlos tenemos que importar y añadir en la sección de imports de app.module.ts:

import { ReactiveFormsModule } from '@angular/forms';

FormControl

Es el objeto qué se usado en los formularios para tener un control sobre su valor y su estado de cada campo en el formulario.

Para usarlo:

nombre= new FormControl('Juan');

FormGroup

Es un conjunto de FormControls, depende del estado de todos sus objetos, si uno de los FormControl es inválido, se invalida el grupo entero. 

Para usarlo:

formGroup = new FormGroup({

nombre: new FormControl('Juan'),
primerApellido: new FormControl('Garcia'),
segundoApellido: new FormControl('Lopez'),
});

Para conectar estos objetos con el formulario del HTML

<form novalidate (ngSubmit)="onSubmit()" [formGroup]="formGroup">
nombre: <input type="text" formControlName="nombre">
primerApellido: <input type="text" formControlName="primerApellido">
segundoApellido: <input type="text" formControlName="segundoApellido">
</form>
Ejemplo:
app.component.ts: 



import { Component, OnInit } from '@angular/core';

import { FormControl, FormGroup } from '@angular/forms';

@Component({

selector: 'app-root',

templateUrl: './app.component.html',

styleUrls: ['./app.component.css']

})

export class AppComponent implements OnInit {

titulo = 'Bienvenido a angular';

formGroup: FormGroup;

persona = {

dni: '',

nombre: '',

primerApellido: '',

segundoApellido: '',

};

constructor() {

}

ngOnInit() {

this.formGroup = new FormGroup({

nombre : new FormControl(''),

primerApellido : new FormControl(''),

segundoApellido : new FormControl('')

});

}

onSubmit() {


this.persona.nombre = this.formGroup.get('nombre').value;

this.persona.primerApellido = this.formGroup.get('primerApellido').value;

this.persona.segundoApellido = this.formGroup.get('segundoApellido').value;

console.log(this.persona.nombre);

console.log(this.persona.primerApellido);

console.log(this.persona.segundoApellido);

}

}

app.component.html:


<form novalidate (ngSubmit)="onSubmit()" [formGroup]=" formGroup">

Nombre: <input type="text" formControlName="nombre">

<br>

PrimerApellido: <input type="text" formControlName="primerApellido">

<br>

SegundoApellido: <input type="text" formControlName="segundoApellido">

<br>

<button type="submit">Enviar</button>

</form>

 

Validadores

Con los validadores vamos a validar la información de los campos del formulario.

Para ello importamos en el componente el modulo Validators:

app.component.ts: 
import { FormControl, FormGroup, Validators } from '@angular/forms' 
 

ngOnInit() {

    this.formGroup = new FormGroup({

    nombre : new FormControl('', [Validators.required, Validators.minLength(2)]),

    primerApellido : new FormControl(''),

    segundoApellido : new FormControl(''),

    contrasena : new FormControl(null, [Validators.required]),

    confirmPassword : new FormControl(null, [Validators.required])

  }, this.comprobarClave);

 

Con Validators.requiered nos vamos que el campo de datos del usuario no este vacio y con minLength y que el nombre del usuario tenga al menos 2 caracteres en el nombre. Si queremos añadir más de un validador, lo podemos hacer mediante un array de validadores.

 

Para las contraseñas:

Primero creamos la siguiente función de comprobar clave:

comprobarClave(form: FormGroup) {

   if (form.get('contrasena') && form.get('confirmPassword')) {

   return form.get('contrasena').value === form.get('confirmPassword').value ? null : { invalido: true };

   }

   return null;

} 

Y despues añadimos la función al FormGroup:

this.formGroup = new FormGroup({

    nombre : new FormControl('', [Validators.required, Validators.minLength(2)]),

    primerApellido : new FormControl(''),

    segundoApellido : new FormControl(''),

    contrasena : new FormControl(null, [Validators.required]),

    confirmPassword : new FormControl(null, [Validators.required])

  }, this.comprobarClave);

 
Para hacer que el boton de submit este deshabilitado mientras que no estén todos los campos validados:

 <button type="submit" [disabled] ="!this.formGroup.valid" >Enviar</button> 

Muestra de errores personalizados:

<div *ngIf="this.formGroup.get('nombre').hasError('required')">

  Nombre requerido

</div>

 
app.component.ts: 

import { Component, OnInit } from '@angular/core';

import { FormControl, FormGroup, Validators  } from '@angular/forms';

@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css']

})

export class AppComponent implements OnInit {

 titulo = 'Bienvenido a angular';

 formGroup: FormGroup;

 persona = {

  dni: '',

  nombre: '',

  primerApellido: '',

  segundoApellido: '',

  contrasena : '',

};

 constructor() {

  }

ngOnInit() {

  this.formGroup = new FormGroup({

    nombre : new FormControl('', [Validators.required, Validators.minLength(2)]),

    primerApellido : new FormControl(''),

    segundoApellido : new FormControl(''),

    contrasena : new FormControl(null, [Validators.required]),

    confirmPassword : new FormControl(null, [Validators.required])

  }, this.comprobarClave);

}

onSubmit() {

  console.log(this.formGroup.value);

  this.persona.nombre = this.formGroup.get('nombre').value;

  this.persona.primerApellido = this.formGroup.get('primerApellido').value;

  this.persona.segundoApellido = this.formGroup.get('segundoApellido').value;

  this.persona.contrasena = this.formGroup.get('contrasena').value;

}

comprobarClave(form: FormGroup) {

   if (form.get('contrasena') && form.get('confirmPassword')) {

   return form.get('contrasena').value === form.get('confirmPassword').value ? null : { invalido: true };

   }

   return null;

}

}

app.component.html:

<form novalidate (ngSubmit)="onSubmit()" [formGroup]="formGroup">

    Nombre: <input type="text" formControlName="nombre">

    <br>

    PrimerApellido: <input type="text" formControlName="primerApellido">

    <br>

    SegundoApellido: <input type="text" formControlName="segundoApellido">

    <br>

    Contraseña : <input type="password" formControlName="contrasena">

    <br>    

    Repite Contraseña: <input type="password" formControlName="confirmPassword">

    <br>

    <button type="submit" [disabled] ="!this.formGroup.valid" >Enviar</button>  

</form>

<div *ngIf="this.formGroup.get('nombre').hasError('required')">

  Nombre requerido

</div>

 

Formularios con FormBuilder

Otra forma de hacer formularios reactivos con angular.

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

A continuacion inyectamos en el constructor:

constructor(private fb: FormBuilder) {}
 
ngOnInit() {
this.formGroup = this.fb.group({
propiedad1 : validadores;
propiedad2 : validadores;
  …………
     propiedad n : validadores; 
}
}

Para recuperar el valor de cada propiedad:

var variable = this.formGroup.get('propiedadn').value;

app.Component.ts:

import { Component, OnInit } from '@angular/core';

import { FormControl, FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css']

})

export class AppComponent implements OnInit {

 titulo = 'Bienvenido a angular';

 formGroup: FormGroup;

 persona = {

  dni: '',

  nombre: '',

  primerApellido: '',

  segundoApellido: '',

  contrasena : '',

};

 

 constructor(private fb: FormBuilder) {

  }

  ngOnInit() {

    this.formGroup = this.fb.group({

      nombre : ['', [Validators.required, Validators.minLength(2)]],

      primerApellido : [''],

      segundoApellido : [''],

      contrasena : [null, Validators.required],

      confirmPassword : [null, Validators.required]

    });

  }

  onSubmit() {

    console.log(this.formGroup.value);

    this.persona.nombre = this.formGroup.get('nombre').value;

    this.persona.primerApellido = this.formGroup.get('primerApellido').value;

    this.persona.segundoApellido = this.formGroup.get('segundoApellido').value;

    this.persona.contrasena = this.formGroup.get('contrasena').value;

  }

}

app.component.html:

<form novalidate (ngSubmit)="onSubmit()" [formGroup]="this.formGroup">

    Nombre: <input type="text" formControlName="nombre">

    <br>

    PrimerApellido: <input type="text" formControlName="primerApellido">

    <br>

    SegundoApellido: <input type="text" formControlName="segundoApellido">

    <br>

    Contraseña : <input type="password" formControlName="contrasena">

    <br>    

    Repite Contraseña: <input type="password" formControlName="confirmPassword">

    <br>

    <button type="submit" [disabled] ="!this.formGroup.valid" >Enviar</button>  

</form>

<div *ngIf="this.formGroup.get('nombre').hasError('required')">

  Nombre requerido

</div>