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.

01/11/2014

Demo

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.

Formulário simples AngularJS

Vamos precisar de dois arquivos:

  • index.html Nosso código para exibir o formulário
  • app.js Nossa aplicação angular e o controlador

Nosso arquivo index.html

<!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 e ng-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.

  1. 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.
  2. 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.
  3. Ajuste as regras de erro de ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }" para ng-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 outros ng-class e ng-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:

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’);

Alert

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