Formularios en Angular 5
Algo que vamos a usar mucho en cualquier página web, son los formularios, con los formularios en angular es muy fácil usar los formularios, si haz utilizado javascript puro, sabemos que hay que capturar datos de cada input, luego «procesarlo» y enviarlo por ajax u otra forma.
Los formularios en angular, nos debemos preocupar solamente, en crear un modelo de nuestro formulario y llamarlo correctamente en el form… tranquilos es mas fácil de lo que parece.
Antes que nada quiero aclarar algo, Explicare solo el funcionamiento del form ya que usare otra entrada pera ser mas especifico en http y explicar este método, ya que hay que entender varios temas extras.
Modelos
Si no sabes que son los modelos en programación orientado a objetos dejare un este link, la explicación breve es que son objetos de información que usaremos entre clases.
para crear el modelo no usaremos angular cli, simplemente vamos a crear la carpeta en nuestro proyecto, por ejemplo models > contactForm.ts, recordemos que ts es por typescript, para nuestros modelos llevara la siguiente estructura que nos servirá en nuestros formularios en angular.
export class ContactForm{ public name:string; public email:string; public phone:number; public subject:string; public msn:string; }
Con Export Class ContactForm estamos diciendo que cuando lo exportemos a otra clase podemos usar nuestras variables, en typescript declaramos nuestra variable y enseguida el tipo de variable por ejemplo.
public name = nombre de variable
name:string = tipo de dato que recibe
Usando Form
Antes de cualquier cosa, debemos agregar las siguientes lineas en nuestro app.module.ts
//importar el modulo de form import { FormsModule } from '@angular/forms'; //en la parte de @ngModule imports: [ BrowserModule, FormsModule ],
Ahora vamos a escribir en nuestra consola del proyecto
ng generate component Contact
Una vez creado, vamos a crear nuestro formulario de toda la vida , pero ahora serán «formularios en angular»
HTML
<form (ngSubmit)="onSubmit(contactForm);" #contactForm="ngForm"> <input matInput placeholder="Nombre" #nombre maxlength="80" [(ngModel)]="ContactModel.name" name="Name" required> <input matInput placeholder="Email" type="email" [(ngModel)]="ContactModel.email" name="Email" required> <input matInput placeholder="Teléfono" #tel type="tel" [(ngModel)]="ContactModel.phone" name="Phone" maxlength="16"> <input matInput placeholder="Asunto" #asunto maxlength="60" [(ngModel)]="ContactModel.subject" name="Subject" required> <textarea matInput placeholder="Mensaje" #msn maxlength="300" [(ngModel)]="ContactModel.msn" name="Msn" cols="25"></textarea> <button [disabled]="!contactForm.form.valid">Enviar</button> </form>
TS
import { Component, OnInit } from '@angular/core'; //componentes de form import {FormControl, Validators} from '@angular/forms'; //modelo creado import {ContactForm} from '../models/contactForm'; //services en angular import {SendEmailService} from '../services/send-email.service'; //libreria rxjs import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; //material desing de angular import {MatSnackBar} from '@angular/material'; // Esta linea fue agregada automaticamente pueden borrarlo import { NgForm } from '@angular/forms/src/directives/ng_form'; @Component({ selector: 'app-contact', templateUrl: './contact.component.html', styleUrls: ['./contact.component.css'] }) export class ContactComponent implements OnInit { //creacion de variable contact ContactModel = new ContactForm(); private emailResponse; private truefalse:boolean = false; constructor(private sendServices: SendEmailService, public snackBar: MatSnackBar) { } ngOnInit() { } onSubmit(f: NgForm){ this.getSentServices(this.ContactModel, f); } //metodo de services getSentServices(body:ContactForm, f: NgForm){ this.sendServices.getResponseEmail(body).subscribe( data => { if(data){ this.snackBar.open("Gracias por el mensaje", "Correcto", { duration: 2000, }); f.reset(); } else{ this.snackBar.open(":(", "Error", { duration: 2000, }); } }, err => { this.snackBar.open("Algo fallo :/, correo: cesar@unprogramador.com", "ups", { duration: 5000, }); } ); } }
Vamos Explicar cada individualmente
TS
En el archivo ts vamos a importar nuestro modelo (puse comentarios para que sea mas fácil) ,
import {ContactForm} from ‘../models/contactForm’;
*ContactForm es el nombre que le pusimos a la clase del model
nos centraremos en el modelo, vamos a crear nuestra variable haciendo una instancia
ContactModel = new ContactForm();
Ya hecho la instancia , podemos usarlo en nuestro html
HTML
<form (ngSubmit)=»onSubmit(contactForm);» #contactForm=»ngForm»>
En la etiqueta form, vamos a ver 2 métodos nuevos
#contactForm es la forma como nosotros podemos poner un id en angular, si colocamos id=»contactForm», vamos a tener un error al compilar.
En #contactForm vamos a definirlo como ngForm, que es la librería que angular a creado para facilitar el trabajo, de esta forma le decimos que esta id es nuestra etiqueta form y por supuesto la principal.
(ngSubmit) es el método que usaremos para enviar todo los valores del formulario a nuestra lógica, lo que en html normal es nuestra propiedad action.
(ngSubmit)=»onSubmit(contactForm);»
onSubmit() es la función que creamos en ts, en este caso paso el id del form para borrar todos los input mediante código, pero no es obligado hacer esta acción.
<input matInput placeholder=»Nombre» #nombre maxlength=»80″ [(ngModel)]=»ContactModel.name» name=»Name» required>
En la línea de arriba explicaremos la nueva propiedad [(ngModel)], con ngModel le estamos diciendo a angular que vamos a introducir un valor a nuestro modelo creado, así que llamamos de la siguiente manera nombrevariable.propiedad.
<button [disabled]=»!contactForm.form.valid»>Enviar</button>
[disabled] es un método de angular para deshabitar, y !contactForm.form.valid estamos validando que todo los campos están llenos, o por lo menos los que le pusimos required, ojo, contactForm es el id del form.
vamos a probar, en nuestro archivo ts vamos a cambiar:
onSubmit(f: NgForm){ this.getSentServices(this.ContactModel, f); }
por
onSubmit(){ console.log(this.ContactModel); }
si abrimos nuestra consola de js, vamos a ver todo los datos al tocar nuestro botón, así que ya sabemos como usar form. dejare unos links donde podrán ver en funcionamiento la página y parte del código.
Actualización
Services SendEmailServices
Para comprender como funcionan estos servicios y como crearlos pueden acceder al siguiente post. y a continuación este es el pequeño código para ejecutar send.php
import { Injectable } from '@angular/core'; import {ContactForm} from '../models/contactForm'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import {HttpClient} from '@angular/common/http'; import 'rxjs/add/operator/map'; @Injectable() export class SendEmailService { type:any; constructor( private http: HttpClient) { } getResponseEmail(_body: ContactForm): Observable<any>{ // this.http.post('/send.php',_body).subscribe(data =>{ // console.log(data); // this.type = JSON.stringify(data); // }); return this.http.post('/send.php',_body); } }
Send.php
send.php es un pequeño fragmento de código que fue programada para mandar correos, este lee las cabeceras de post de Angular y decodifica, el metodo Mail viene por default en php pero en algunos hosting pueden no tenerlo configurado por default.
Nota:
$Send_to: sirve para la mascara del correo (quien lo envia)
$from: es el correo que vamos a recibir
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: X-Requested-With'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); $postdata = file_get_contents("php://input"); $request = json_decode($postdata); $email = $request->email; $pass = $request->password; $name= $request->name; $phone=$request->phone; $email= $request->email; $company=$request->subject; $text=$request->msn; $send_to = ""; $from = ""; $body=' <html> <head> <title>Ingrese titulo</title> </head> <body> <table cellpadding="15" cellspacing="0"> <tr> <td><th>Name</th></td> <td> '.$name.' </td> </tr> <tr> <td><th>Email</th><td>'. $email .'</td> </tr> <tr> <td><th>Telephone</th></td><td> '.$phone.' </td> </tr> <tr> <td><th>Mensaje</th></td><td>'.$text.'</td> </tr> </table> </body> </html> '; $head = 'MIME-Version: 1.0' . "\r\n"; $head .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; $head .= 'From: ' . $from . "\r\n"; if(mail($send_to,$company,$body ,$head)){ echo json_encode(true); } else{ echo json_encode(false); }
Explicacion de consumir webservices con angular
Hola Cesar espero estes bien, muchas gracias por el post Cesar. tengo una duda, al colocar el servicio en el constructor de mi contact me sale este error en el navegador
Error: «StaticInjectorError(AppModule)[SendEmailService -> HttpClient]:
StaticInjectorError(Platform: core)[SendEmailService -> HttpClient]:
NullInjectorError: No provider for HttpClient!»
tienes idea que puede ser?
Muchas gracias
Hola gonzalo gracias por leer el post, los services que creastes tienes que registrarlo en el appmodule y colocarlos en el providers para que se registre y lo puedas usar te dejo un ejemplo de cómo se ve https://gitlab.com/tutorialesup/subirarchivosng/blob/develop/src/app/app.module.ts
Muchas gracias por pronta respuesta! Saludos
Cualquier duda dejame un comentario, tratare de responderlo lo mas rapido posible
disculpa la ignorancia, en el archivo send.php en las lineas
$email = $request->email;
$pass = $request->password
debo colocar el mail y el password con el que voy a mandar el mail?
Gracias!
Lo que hago ahi es recibir el metodo post del solicitante(lo envia del form de angular al php) , es decir son valores que yo voy a ver cuando me llega el correo, te recomiendo si vas a probar el email, configures el modulo de xampp para envios de correos o uses un hosting con envio de correos de php ya que el cli de angular no levanta servicios de php
Buenos dias Cesar Flores! excelente el tutorial, muy bien explicado. Pero tengo un problema, a la hora de enviar el correo lo envia sin ningún problema pero el correo me llega una vez vacío y otra vez con los datos correctos. Cual seria el problema? El código lo tengo tal cual lo explicaste en esta publicación. Saludos
nunca me habia pasado algo asi, podria ser que tus documentos en php están tomando cache o tus modelos queden basura al inicializarlo lo que puedes hacer es imprimir el modelo que pasas al services, ahi veras si siempre estan pasando los datos llenos, si pasa esa prueba checa tu php que no este tomando cache para esto puedes agregarle el siguiente codigo al iniciar tu archivo php
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
Mi pana buen tutorial, pero tengo una duda, en donde debo colocar el archivo send.php?
Hola Jorge, yo lo tengo en la raíz del servidor, pero lo puedes poner donde quieras solo debes hacer bien la referencia
tengo el código tal cual lo tienes en el tutorial, pero recibo estos errores al darle click a enviar:
POST http://localhost:4200/send.php 404 (Not Found)
ERROR TypeError: Cannot read property ‘open’ of undefined y otras cosas mas.
Aaah el servidor que levanta angular no acepta php , tendrás que bajarte un servidor y configurar el envío de correo (perl) como xampp y no olvides de bajar un pluging para los CORP
Gracias por tu respuesta amigo, cree el build y copie la carpeta dist en htdocs del xampp y ya logré solucionar esos errores, pero ahora el problema es que me sale solo el error del SnackBar de que algo falló, no tendrás algún medio donde pueda enviarle mi codigo para que lo vea? Si puede claro está y muchas gracias de antemano
Es muy probable que te falle porque material Angular fue actualizado(junio) te recomiendo que cheques la página oficial https://material.angular.io/components/snack-bar/overview o también puedes crear un propio modal 😉 cualquier cosa puedes contactarme en shingrey@unprogramador.com y trataré de dar un espacio un saludo!
Hola Cesar un placer, gracias por compartir tus conocimientos,
Estoy incursionando en el mundo de angular y me gustaría saber si me puedes ayudar con algo que estoy creando una vista con 3 componentes separados
tengo un componente global donde incluyo al componente formulario y al componente barra de tareas que es donde van
los botones de llamado a servicios, guardar, eliminar entre otros.
Ahora bien, lo que no se es como pasarle los datos del componente formulario al componente barra de tareas, que al darle click a la barra de tareas el tenga todos los datos del formulario(nombre, apellido, teléfono), no se si me explico bien?
vista-general.html
Quedo atenta a tu respuesta, gracias.
hola que tal mari, un saludo te invito a leer el siguiente post https://unprogramador.com/crear-slider-con-angular-usando-inputs/
pero en resumen, tu puedes usar las propiedades @Input de angular, este escucha parametros de otros componentes
un ejemplo que puedo dar es que en tu componente que escucha algo le programes los inputs
//componente 1
@Input nombre:string;
y en tu formulario o donde este el componente 1 lo llamas de la siguiente manera
//componente 2
//html
//componente 2.ts
En el evento del formulario puedes hacer lo siguiente
eventoForm(){
this.nombreform = model.miformularioNombre;
}
la ventaja de los inputs es que puedes enviar cualquier informacion (texto) y tambien puedes regresar, a esto se le encuentra como Output (@output)
si tienes otra duda puedes dejar otro comentario y tratare de ayudarte
Hola Cesar: de verdad muy bueno el post! hay muy poca informacion en internet para resolver algo tan comun como esto. Se agradece muchisimo tu trabajo.
Quisiera saber si es posible resolver una duda acerca de un error que me sale:
this.sendServices.getResponseEmail(…).subscribe is not a function at
muchas gracias
saludos
Hola pablo muchas gracias , lo que pasa es que tienes que crear un servicio y luego llamarlo te dejare la clase que llama y la explicacion a continuacion
Esta es la clase https://gitlab.com/shingrey/WebPageAngular/blob/develop/src/app/services/send-email.service.ts
Aqui explico un poco sobre como funciona los services y como se crean
https://unprogramador.com/consumir-webservices-con-angular-y-httpclient/
Cualquier duda no dudes ponerlo en los comentarios
Gracias Cesar, me fue de mucha utilidad!
de nada cualquier duda, sugerencia o tema en especifico no dudes en contactarnos un saludo
Qual github do projeto ? muito bom seu site !
https://gitlab.com/users/shingrey/projects
https://github.com/shingrey
El proyecto del form https://gitlab.com/shingrey/WebPageAngular/tree/develop
Saludos