Reactive Forms
Reactive Forms é uma das duas maneiras de criar formulários com o Angular.
Nesse tutorial você vai aprender
- Criar um formulário com um componente
- Usar o formControlName para criar o two-way data bindings para ler e escrever nos inputs na tela
- Como limpar os campos na tela após submeter o formulário
Pré-requisitos
Esse tutorial foi feito utilizando o bootstrap para criação de uma interface mais amigável. Se você não sabe o que é o bootstrap, clique aqui para ver o tutorial.
Também foi utilizada a versão 7.0 do Angular.
Passo a passo para a criação do formulário
- Instalação do ReactiveFormsModule
- Criar a classe que será o modelo do formulário
- Criar o componente com o formulário
- Aplicar o formGroup no formulário formControlName nos inputs
- Fazer o formulário submter
1 – Instalação do ReactiveFormsModule
Antes de começar, você precisa importar o módulo ReactiveFormsModule no seu projeto.
Esse modulo possui todas as diretivas de criação de formulários do tipo Reactive Forms. É necessário efetuar o import antes de qualquer componente que use um formulário.
Para importar, é só incluir a linha abaixo no arquivo app.module.ts.
import { ReactiveFormsModule } from '@angular/forms';
O arquivo app.module.ts deve ficar assim:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2 – Criar a classe que será o modelo do formulário
Para esse exemplo, será criado uma classe de cliente com os campos abaixo.
Para criar uma classe é só rodar o comando abaixo.
ng g class clientes/shared/cliente
O arquivo cliente.ts deve ficar assim:
export class Cliente {
nome: string = '';
tipo: number = 1;
genero: number = 1;
dataNascimento: Date = null;
observacao: string = '';
inativo: boolean = false;
}
3 – Criar o componente com o formulário
O formulário no Angular é um formulário comum com a adição do formControlName para fazer o binding entre o controle na tela e o objeto de formulário que você está usando.
Criar o componente
Para criar o componente que terá o formulário, é só rodar o comando abaixo
ng g component clientes/formulario
A principio o arquivo formulario.component.html deve ficar assim:
<form>
<div class="form-group">
<label for="nome">Nome</label>
<input type="text" class="form-control" name="nome" id="nome" required>
</div>
<div class="form-group">
<label for="tipo">Tipo</label>
<select class="form-control" name="tipo" id="tipo">
<option value="1">Pessoa física</option>
<option value="2">Pessoa jurídica</option>
</select>
</div>
<div class="form-group">
<label>Gênero</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="masculino" [value]="1">
<label class="form-check-label" for="masculino">Masculino</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="feminino" [value]="2">
<label class="form-check-label" for="feminino">Feminino</label>
</div>
</div>
<div class="form-group">
<label for="dataNascimento">Data de nascimento</label>
<input type="date" class="form-control" name="dataNascimento" id="dataNascimento">
</div>
<div class="form-group">
<label for="observacao">Observação</label>
<textarea class="form-control" rows="3" name="observacao" id="observacao"></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="inativo" id="inativo">
<label class="form-check-label" for="inativo">Inativo</label>
</div>
<input type="submit" class="btn btn-primary mt-4" value="Salvar">
<a href="#" class="btn btn-secondary mt-4 ml-2">Cancelar</a>
</form>
Criação do objeto de formulário
Para fazer o binding na tela, é necessário criar um objeto que será um agrupador de inputs que existiram na tela. Esse objeto é do tipo FormGroup e os inputs são do tipo FormControl. Para criar esse objeto, você pode usar diretamente os tipos mencionados acima ou usar o FormBuilder.
Exemplo 1: Usando diretamente os tipos.
É necessário fazer o import abaixo no componente
import { FormGroup, FormControl } from '@angular/forms';
Agora é necessário criar uma função para criação do objeto do formulário
createForm(cliente: Cliente) {
this.formCliente = new FormGroup({
nome: new FormControl(cliente.nome),
tipo: new FormControl(cliente.tipo),
genero: new FormControl(cliente.genero),
dataNascimento: new FormControl(cliente.dataNascimento),
observacao: new FormControl(cliente.observacao),
inativo: new FormControl(cliente.inativo)
})
}
O arquivo formulario.component.ts deve ficar assim:
import { Component, OnInit } from '@angular/core';
import { Cliente } from '../shared/cliente';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-formulario',
templateUrl: './formulario.component.html',
styleUrls: ['./formulario.component.scss']
})
export class FormularioComponent implements OnInit {
formCliente: FormGroup;
constructor() { }
ngOnInit() {
this.createForm(new Cliente());
}
createForm(cliente: Cliente) {
this.formCliente = new FormGroup({
nome: new FormControl(cliente.nome),
tipo: new FormControl(cliente.tipo),
genero: new FormControl(cliente.genero),
dataNascimento: new FormControl(cliente.dataNascimento),
observacao: new FormControl(cliente.observacao),
inativo: new FormControl(cliente.inativo)
})
}
}
Exemplo 2: Usando o FormBuilder.
É necessário fazer o import abaixo no componente
import { FormBuilder, FormGroup } from '@angular/forms';
No construtor do componente você receber uma instancia do objeto FormBuilder por injeção de dependencia
constructor(private formBuilder: FormBuilder) { }
Agora é necessário criar uma função para criação do objeto do formulário
createForm(cliente: Cliente) {
this.form = this.formBuilder.group({
nome: [cliente.nome],
tipo: [cliente.tipo],
genero: [cliente.genero],
dataNascimento: [cliente.dataNascimento],
observacao: [cliente.observacao],
inativo: [cliente.inativo]
})
}
O arquivo formulario.component.ts deve ficar assim:
import { Component, OnInit } from '@angular/core';
import { Cliente } from '../shared/cliente';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-formulario',
templateUrl: './formulario.component.html',
styleUrls: ['./formulario.component.scss']
})
export class FormularioComponent implements OnInit {
formCliente: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.createForm(new Cliente());
}
createForm(cliente: Cliente) {
this.formCliente = this.formBuilder.group({
nome: [cliente.nome],
tipo: [cliente.tipo],
genero: [cliente.genero],
dataNascimento: [cliente.dataNascimento],
observacao: [cliente.observacao],
inativo: [cliente.inativo]
})
}
}
Exibir o formulário na tela
Para ver o resultado na tela, é necessário incluir o componente de formulário no componente raiz da aplicação app.component.
O arquivo app.component.html deve ficar assim:
<app-formulario></app-formulario>
4 – Aplicar o formGroup no formulário formControlName nos inputs
Primeiro é necessário fazer o binding do tag form com o objeto de formulário criado.
Para isso é só adicionar a diretiva [formGroup] na tag form com o valor do nome do objeto criado para o formulário.
No exemplo acima foi criado um objeto de nome “formCliente”, logo ele será o valor do [formGroup].
<form [formGroup]="formCliente">
Agora é hora de usar a diretiva formControlName para poder fazer o binding dos controles.
Para isso em cada input na tela será colocado o formControlName.
O arquivo formulario.component.html deve ficar assim:
<form [formGroup]="formCliente">
<div class="form-group">
<label for="nome">Nome</label>
<input type="text" class="form-control" name="name" id="nome" formControlName="nome">
</div>
<div class="form-group">
<label for="tipo">Tipo</label>
<select class="form-control" name="tipo" id="tipo" formControlName="tipo">
<option value="1">Pessoa física</option>
<option value="2">Pessoa jurídica</option>
</select>
</div>
<div class="form-group">
<label>Gênero</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="masculino" [value]="1" formControlName="genero">
<label class="form-check-label" for="masculino">Masculino</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="feminino" [value]="2" formControlName="genero">
<label class="form-check-label" for="feminino">Feminino</label>
</div>
</div>
<div class="form-group">
<label for="dataNascimento">Data de nascimento</label>
<input type="date" class="form-control" name="dataNascimento" id="dataNascimento" formControlName="dataNascimento">
</div>
<div class="form-group">
<label for="observacao">Observação</label>
<textarea class="form-control" rows="3" name="observacao" id="observacao" formControlName="observacao"></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="inativo" id="inativo" formControlName="inativo">
<label class="form-check-label" for="inativo">Inativo</label>
</div>
<input type="submit" class="btn btn-primary mt-4" value="Salvar">
<a href="#" class="btn btn-secondary mt-4 ml-2">Cancelar</a>
</form>
Com isso todo valor que você digitar na tela será salvo na respectiva propriedade do objeto “formCliente” e todo valor que você colocar em alguma propriedade do “formCliente” será exibido na tela.
Um exemplo disso é mostrado no vídeo acima.
5 – Fazer o formulário submter
Para fazer o formulário submeter é necessário criar um método no arquivo formulario.component.ts e adicionar a chamada desse método no evento (ngSubmit) do formulário.
Método para submeter o formulário
onSubmit() {
// aqui você pode implementar a logica para fazer seu formulário salvar
console.log(this.formCliente.value);
}
E na tag form adicionar
(ngSubmit)="onSubmit()"
Limpando os campos do formulário
Para limpar os valores preenchidos na tela de maneira você tem duas opções.
Opção 1: Chamar novamente a função createForm com um novo objeto de cliente.
onSubmit() {
// aqui você pode implementar a logica para fazer seu formulário salvar
console.log(this.formCliente.value);
// chamando a função createForm para limpar os campos na tela
this.createForm(new Cliente());
}
Opção 2: Usar o método reset do formCliente
onSubmit() {
// aqui você pode implementar a logica para fazer seu formulário salvar
console.log(this.cliente);
// Usar o método reset para limpar os controles na tela
this.formCliente.reset(new Cliente());
}
O exemplo completo do arquivos formulario.component.ts e formulario.component.html está abaixo:
Arquivo formulario.component.ts
import { Component, OnInit } from '@angular/core';
import { Cliente } from '../shared/cliente';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-formulario',
templateUrl: './formulario.component.html',
styleUrls: ['./formulario.component.scss']
})
export class FormularioComponent implements OnInit {
formCliente: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.createForm(new Cliente());
}
createForm(cliente: Cliente) {
this.formCliente = this.formBuilder.group({
nome: [cliente.nome],
tipo: [cliente.tipo],
genero: [cliente.genero],
dataNascimento: [cliente.dataNascimento],
observacao: [cliente.observacao],
inativo: [cliente.inativo]
})
}
onSubmit() {
// aqui você pode implementar a logica para fazer seu formulário salvar
console.log(this.formCliente.value);
// Usar o método reset para limpar os controles na tela
this.formCliente.reset(new Cliente());
}
}
Arquivo formulario.component.html
<form [formGroup]="formCliente" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="nome">Nome</label>
<input type="text" class="form-control" name="name" id="nome" formControlName="nome">
</div>
<div class="form-group">
<label for="tipo">Tipo</label>
<select class="form-control" name="tipo" id="tipo" formControlName="tipo">
<option value="1">Pessoa física</option>
<option value="2">Pessoa jurídica</option>
</select>
</div>
<div class="form-group">
<label>Gênero</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="masculino" [value]="1" formControlName="genero">
<label class="form-check-label" for="masculino">Masculino</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="genero" id="feminino" [value]="2" formControlName="genero">
<label class="form-check-label" for="feminino">Feminino</label>
</div>
</div>
<div class="form-group">
<label for="dataNascimento">Data de nascimento</label>
<input type="date" class="form-control" name="dataNascimento" id="dataNascimento" formControlName="dataNascimento">
</div>
<div class="form-group">
<label for="observacao">Observação</label>
<textarea class="form-control" rows="3" name="observacao" id="observacao" formControlName="observacao"></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="inativo" id="inativo" formControlName="inativo">
<label class="form-check-label" for="inativo">Inativo</label>
</div>
<input type="submit" class="btn btn-primary mt-4" value="Salvar">
<a href="#" class="btn btn-secondary mt-4 ml-2">Cancelar</a>
</form>
Referências
- Documentação do Reactive Forms: https://angular.io/guide/reactive-forms
- Instalação do bootstrap: https://www.fabricadecodigo.com/bootstrap-instalacao-angular/
- Template-driven Forms: https://www.fabricadecodigo.com/criar-formulario-template-driven-forms/