Diretiva ngForm em Angular
Geralmente, ao trabalhar com formulários, todos os elementos de entrada não são definidos isoladamente, mas são colocados dentro de um elemento de formulário padrão: <form></form>
. Utilizar esse elemento permite gerenciar todos os campos de entrada como um formulário único.
No Angular, a diretiva especial NgForm
foi criada para manipulação de formulários. Ela gera um objeto FormGroup
e o associa ao formulário, permitindo rastrear o estado do formulário e gerenciar sua validação.
Podemos aplicar essa diretiva definindo uma variável na tag do formulário:
<form #myForm="ngForm"></form>
Embora ao usar formulários não seja obrigatório utilizar essas variáveis que representam o formulário como um todo, ao utilizá-las, podemos obter algumas funcionalidades adicionais. Em particular, podemos acessar o status do formulário através dessa variável.
Por exemplo, veja o seguinte componente AppComponent
:
import { Component } from "@angular/core";
import { FormsModule, NgForm } from "@angular/forms";
class User {
constructor(public name: string, public email: string, public phone: string) {}
}
@Component({
selector: "my-app",
standalone: true,
imports: [FormsModule],
styles: `
input.ng-touched.ng-invalid {border: solid red 2px;}
input.ng-touched.ng-valid {border: solid green 2px;}
`,
template: `<form #myForm="ngForm" novalidate>
<p>
<label>Nome</label><br />
<input name="name" [(ngModel)]="name" required />
</p>
<p>
<label>Email</label><br />
<input name="email" ngModel required email />
</p>
<p>
<label>Telefone</label><br />
<input name="phone" ngModel required pattern="[0-9]{10}" />
</p>
<button [disabled]="myForm.invalid" (click)="submit(myForm)">Adicionar</button>
</form>
<p>Nome: {{ myForm.value.name }}</p>
<p>Email: {{ myForm.value.email }}</p>`,
})
export class AppComponent {
name: string = "";
email: string = "";
phone: string = "";
submit(form: NgForm) {
console.log(form);
}
}
Para utilizar a diretiva NgForm
, é necessário importá-la do pacote "angular/forms"
:
import { NgForm } from "@angular/forms";
No formulário, foi definida a variável #myForm
, que é inicializada com o valor "ngForm"
. Isso significa que a variável myForm
representa a diretiva NgForm
, e através dessa variável podemos acessar todo o formulário.
Mesmo que não tenhamos explicitamente adicionado a diretiva NgForm
, o Angular automaticamente a aplica à tag do formulário. Essa diretiva adiciona várias funcionalidades ao elemento form
. Em particular, ela encapsula todos os elementos do formulário que utilizam a diretiva ngModel
, permitindo acessar o estado desses elementos, além de validar os dados inseridos. Para rastrear o estado, o Angular adiciona algumas classes à tag do formulário:
<form class="ng-pristine ng-untouched ng-valid" novalidate=""></form>
As classes ng-pristine
, ng-untouched
, e ng-valid
são as mesmas que se aplicam aos elementos de controle e que foram discutidas no tema anterior.
A seguir, podemos utilizar o formulário, principalmente para sua validação. Primeiramente, o formulário utiliza o atributo "novalidate"
, que desativa a exibição das mensagens de erro de validação padrão do navegador. Isso ocorre porque, nesse caso, confiamos no mecanismo de validação do Angular. E, na prática, uma forma que é válida para o Angular nem sempre será considerada válida pelo navegador.
Em segundo lugar, utilizando o estado do formulário, podemos desabilitar o botão, evitando certas ações quando ele for pressionado:
<button [disabled]="myForm.invalid"></button>
No método submit()
, que é chamado ao clicar no botão, também podemos acessar o formulário inteiro e seus valores:
onSubmit(myForm: NgForm) {
console.log(myForm);
}
Os elementos do formulário utilizam a diretiva ngModel
. Apenas em um caso usamos uma expressão de vinculação. A vinculação com ngModel
não é obrigatória, embora seja comumente usada na forma de vinculação bidirecional. A diretiva ngModel
simplesmente indica que o campo de entrada ao qual é aplicada será incluído no objeto myForm
.
Ao trabalhar com a variável myForm
, é importante lembrar que ela representa um objeto que encapsula todas as informações do formulário.
Por exemplo, através da propriedade controls
, podemos acessar os elementos do formulário aos quais foi aplicada a diretiva ngModel
. Os nomes desses elementos correspondem aos valores do atributo name
dos campos de entrada.
Para obter os valores inseridos, também podemos utilizar a propriedade value
:
<p>Nome: {{myForm.value.name}}</p>
<p>Email: {{myForm.value.email}}</p>
É importante destacar que o acesso ao elemento correspondente só será possível se a diretiva ngModel
for aplicada ao campo, como visto nos exemplos acima.
Envio de Formulário
Após preencher o formulário, o usuário geralmente o envia clicando em um botão de envio (<input type="submit" />
), que costuma ser colocado na parte inferior do formulário. No Angular, para gerenciar o envio do formulário, podemos utilizar o evento ngSubmit
, que é disparado ao clicar no botão de envio:
import { Component } from "@angular/core";
import { FormsModule, NgForm } from "@angular/forms";
class User {
constructor(public name: string, public email: string, public phone: string) {}
}
@Component({
selector: "my-app",
standalone: true,
imports: [FormsModule],
styles: `
input.ng-touched.ng-invalid {border: solid red 2px;}
input.ng-touched.ng-valid {border: solid green 2px;}
`,
template: `<form #myForm="ngForm" novalidate (ngSubmit)="onSubmit(myForm)">
<p>
<label>Nome</label><br />
<input name="name" ngModel required />
</p>
<p>
<label>Email</label><br />
<input name="email" ngModel required email />
</p>
<p>
<label>Telefone</label><br />
<input name="phone" ngModel required pattern="[0-9]{10}" />
</p>
<input type="submit" [disabled]="myForm.invalid" value="Enviar" />
</form>`,
})
export class AppComponent {
name: string = "";
email: string = "";
phone: string = "";
onSubmit(form: NgForm) {
console.log(form);
}
}
Nesse caso, ao gerar o evento ngSubmit
, o método onSubmit()
definido no componente será acionado. Utilizando esse método, podemos processar os dados enviados diretamente ou realizar algum tipo de pré-processamento antes de enviá-los para o servidor.