AngularJS Validação de Formulário
Vamos focar a validação do lado do cliente e usando as propriedades de formulário angular. Aqui está uma demonstração rápida.
Nov 1, 2014Tempo de leitura 4 minDemo
See the Pen KDosE by Airton Vancin Junior (@airton) on CodePen.
Para começar vamos listar os requisitos do formulário
Requisitos
- name é obrigatório
- username não é necessária, comprimento mínimo de 3 caracteres e comprimento máximo de 8 caracteres
- email não é obrigatório, mas tem que ser um e-mail válido
- Formulário de envio é desativado se o formulário não é válido
- Mostrar um erro de e-mail obrigatório ou inválido
- Monstrar uma mensagem de alerta se estiver tudo correto
Agora que sabemos o que queremos, vamos começar a construção.
Propriedades do formulário Angular
$valid
, $invalid
, $pristine
, $dirty
O Angular fornece propriedades que nos ajudam a validá-los.
Propriedade | Classe | Descrição |
$valid | ng-valid | Boolean Diz se um item é válido no momento com base nas regras que você colocou. |
$invalid | ng-invalid | Boolean Diz se um item está inválida com base nas regras que você colocou. |
$pristine | ng-pristine | Boolean Verdadeiro se o form/input ainda não foi usado |
$dirty | ng-dirty | Boolean Verdadeiro se o form/input foi usado. |
O Angular também oferece classes de acordo com as entradas de modo que você pode estilizar cada estado do formulário.
Acessando as propriedades do formulário Angular
Para acessar o formulário:
"form name"."angular property"
ex:userForm.$valid
Para acessar o input:
"form name"."input name"."angular property"
ex:userForm.name.$valid
Configurando nosso Formulário
Vamos usar um formulário simples para demonstrar.
Vamos precisar de dois arquivos:
index.html
Nosso código para exibir o formulárioapp.js
Nossa aplicação angular e o controlador
<!DOCTYPE html>
<html>
<head>
<!-- load bootstrap css -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<style>
body { padding-top:30px; }
</style>
<!-- load angularJS -->
<script src="http://code.angularjs.org/1.2.6/angular.js"></script>
<script src="app.js"></script>
</head>
<!-- aplicar app angular e controlador para o nosso body -->
<body ng-app="validationApp" ng-controller="mainController">
<div class="container">
<div class="col-sm-8 col-sm-offset-2">
<!-- PAGE HEADER -->
<div class="page-header"><h1>AngularJS Validação de Formulário</h1></div>
<!-- FORM -->
<!-- passa a variável se nosso formulário é válida ou inválida -->
<!-- novalidate isso vai evitar a validação padrão do HTML5, já que vamos fazer isso usando o Angular -->
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
<!-- NAME -->
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="name" required>
</div>
<!-- USERNAME -->
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
</div>
<!-- EMAIL -->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="email">
</div>
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-primary">Enviar</button>
</form>
</div><!-- col-sm-8 -->
</div><!-- /container -->
</body>
</html>
Alguns pontos importantes a observar aqui:
- novalidate: isso vai evitar a validação padrão do HTML5, já que vamos fazer isso usando o Angular (o nosso será muito mais bonito)
- Temos aplicado
ng-model
para poder vincular os dados do nosso formulário a variáveis ng-minlength
eng-maxlength
no nome de usuário vai criar essas regras de introdução- O input
name
é required - O input
e-mail
é type = "email"
Regras de Validação
Angular oferece muitas regras de validação que podemos usar, além de ng-minlength
e ng-maxlength
.
Estes são os parâmetros disponíveis para uma entrada angular para criar regras de validação. Leia a Angular input directive para mais informações.
<input
ng-model="{ string }"
name="{ string }"
required
ng-required="{ boolean }"
ng-minlength="{ number }"
ng-maxlength="{ number }"
ng-pattern="{ string }"
ng-change="{ string }"
ng-trim="{ boolean }">
</input>
Agora que temos a nosso formulário simples, vamos criar nosso aplicativo Angular e controlador que já aplicou a ele usando ng-app
e ng-controller
.
Nosso código Angular app.js
// app.js
// criar angular app
var validationApp = angular.module('validationApp', []);
// criar angular controller
validationApp.controller('mainController', function($scope) {
// função para enviar o formulário depois que a validação estiver ok
$scope.submitForm = function(isValid) {
// verifica se o formulário é válido
if (isValid) {
alert('Formulário OK');
}
};
});
Desabilitar validação HTML5 novalidate
Usaremos novalidate
no nosso formulário. Esta é uma boa prática, pois não queremos usar a validação nativa do navegador.
Desabilitar o botão Enviar ng-disabled
Agora começa a verdadeira diversão. Temos que começar a usar propriedades angulares. Primeiro vamos desativar o nosso botão enviar. Nós só queremos que o botão fique habilitado quando a validação estiver correta, então vamos usar a propriedade $invalid
.
<!-- index.html -->
...
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-primary" ng-disabled="userForm.$invalid">Enviar</button>
...
Com apenas esse pequeno código (ng-disable
), o nosso botão de formulário será desativado se o formulário for $invalid
. Isto significa que o nosso campo de entrada de name
é obrigatório e nosso campo de entrada de e-mail
requer um e-mail válido.
Mostrando uma mensagem de erro ng-show
ng-valid e ng-invalid irá determinar automaticamente se uma entrada é uma boa base nas regras colocadas sobre ele em seu formulário.
Vamos percorrer e adicionar uma mensagem de erro para cada uma de nossas entradas, se não forem $valid
e já foram usados (uma vez que não queremos mostrar um erro antes de terem sido utilizados).
<!-- index.html -->
...
<!-- NAME -->
<div class="form-group">
<label>Nome</label>
<input type="text" name="name" class="form-control" ng-model="user.name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">Seu nome é obrigatório</p>
</div>
<!-- USERNAME -->
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">Username no mínimo 3 caracteres.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username no máximo 8 caracteres.</p>
</div>
<!-- EMAIL -->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="user.email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Informe um e-mail válido.</p>
</div>
...
Só assim, angular irá determinar automaticamente se devemos mostrar um erro baseado em uma entradas $invalid
e $pristine
propriedades.
Estilizando as classes
O Angular já oferece as classes css em nosso formulário, baseando se nossos campos são válidos ou inválidos. Veja a tabela no começo do post com as classes (ng-valid
, ng-invalid
, ng-pristine
e ng-dirty
).
Você pode estilizar o formulário usando essas classes, se quiser. Você pode fazer o que quiser com essas classes.
.ng-valid { }
.ng-invalid { }
.ng-pristine { }
.ng-dirty { }
/* really specific css rules applied by angular */
.ng-invalid-required { }
.ng-invalid-minlength { }
.ng-valid-max-length { }
Adicionando Classes condicionais ng-class
Como estamos usando Bootstrap, vamos utilizar as classes que eles fornecem (has-error
).
O ng-class
nos permite adicionar classes com base em uma expressão. Neste caso, nós queremos adicionar uma classe has-error
no nosso form-group, se uma entrada é $invalid
e não pristine
.
O modo como funciona é ng-class="{ < nome-da-classe > : < expressão a ser avaliada > }"
Para mais informações, leia o Angular ngClass docs.
<!-- index.html -->
...
<!-- NAME -->
<div class="form-group" ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }">
<label>Nome</label>
<input type="text" name="name" class="form-control" ng-model="user.name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">Seu nome é obrigatório</p>
</div>
<!-- USERNAME -->
<div class="form-group" ng-class="{ 'has-error' : userForm.username.$invalid && !userForm.username.$pristine }">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">Username no mínimo 3 caracteres.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username no máximo 8 caracteres.</p>
</div>
<!-- EMAIL -->
<div class="form-group" ng-class="{ 'has-error' : userForm.email.$invalid && !userForm.email.$pristine }">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="user.email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Informe um e-mail válido.</p>
</div>
...
Agora nosso formulário tem as classes de erro do Bootstrap corretas.
Só mostrar os erros depois que enviar o formulário
Às vezes não é desejável para mostrar erros enquanto o usuário está digitando. Os erros atualmente mostram imediatamente como um usuário está a preencher o formulário. Isso acontece por causa da grande característica de ligação de dados do Angular. Uma vez que tudo muda imediatamente, pode ser uma desvantagem quando se fala de validação de formulário.
Para o cenário onde você só quer mostrar erros depois de um formulário é enviado, você poderia ajustar o código acima um pouco.
- Você precisaria tirar o
ng-disabled
no botão enviar, para qe o usuário possa enviar o formulário, mesmo que não é totalmente válido. - Você gostaria de acrescentar uma variável após o formulário ser submetido. Dentro da sua função
submitForm()
, basta adicionar$scope.submitted = true;
. Este armazena a variável apresentada como verdade, logo que o formulário é enviado. - Ajuste as regras de erro de
ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }"
parang-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine && submitted }"
. Isso garante que o erro só será exibido após o formulário é enviado. Você precisará ajustar todos os outrosng-class
eng-show
para explicar essa variável.
Agora, o formulário só mostra erros se a variável submitted
é definido como verdadeiro.
Só mostrar erros após clicar fora de uma entrada
Apenas mostrando erros após clicar fora de uma entrada (também conhecida como blur) é um pouco mais complicado do que validar em enviar. Validando um formulário no blur requer uma custom directive. A directiva permitirá que você manipule o DOM.
Aqui estão alguns recursos para criar diretivas personalizadas para lidar com blur:
- http://coding-issues.blogspot.in/2013/10/angularjs-blur-directive.html
- http://blog.ejci.net/2013/08/06/dealing-with-focus-and-blur-in-angularjs-directives/
- http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview
Tudo feito
Agora preenchemos nossas informações corretamente no nosso formulário o botão de envio estará ativo, e ao enviar aparecera a mensagem de alerta que montamos. alert('Formulário OK');
Com apenas algumas linhas simples que temos agora:
- Validação de Entrada
- Form Errors
- Classes customizadas
- Automaticamente desabilitada e habilitada forma
- Regras personalizadas
Como você pode ver, é fácil de usar o construída em técnicas de validação forma angular para criar um formulário validado no lado do cliente.
O Futuro
Tal como está, não é um processo simples para fazer a validação depois que um usuário clica fora de uma entrada. A equipe é Angular ciente disso e eles disseram que planejam adicionar mais estados para lidar com coisas como form.submitted
, input.$visited
, input.$blurred
, ou input.$touched
.
Aqui estão alguns recursos para o futuro da validação de formulário:
- Github Issue
- ngForm Module Ideas
Suporte
Nota: AngularJS 1.3 não tem suporte para IE8. Leia mais sobre isso no blog do AngularJS. AngularJS 1.2 continuará com suporte ao IE8, mas a equipe principal não pretende gastar tempo com endereçamento específicos para o IE8.
Nota: Esse é uma tradução do post original http://scotch.io/tutorials/javascript/angularjs-form-validation