Validação de formulário AngularJS no envio: $dirty, $valid e $invalid

⚡ Resumo Inteligente

A validação de formulários no AngularJS verifica se os dados inseridos em um formulário estão corretos e completos antes de chegarem ao servidor. Quatro abordagens são abordadas aqui, desde atributos HTML5 simples, passando por propriedades de escopo, até módulos de validação automática.

  • 🧩 Atributos HTML5: O atributo obrigatório e os tipos de entrada de e-mail, senha e número oferecem verificações nativas do navegador sem a necessidade de scripts.
  • 🔍 Propriedades do Estado: O AngularJS expõe as variáveis ​​`$dirty`, `$pristine`, `$valid` e `$invalid` em todos os controles nomeados dentro de um formulário nomeado.
  • 🏷️ Requisito de nomenclatura: Tanto o formulário quanto cada controle precisam de um atributo "name", porque o estado de validação é acessado como nomeDoFormulário.nomeDoControle.
  • 🚫 Suprimir pop-ups nativos: Adicionar `novalidate` ao formulário impede que o navegador intercepte o envio, permitindo que o AngularJS o processe.
  • 💬 Exibição de mensagem: O módulo ngMessages substitui as diretivas ng-show empilhadas e exibe um erro por vez, em ordem de prioridade.
  • ⚙️ Validação automática: O módulo jcs-autoValidate gera mensagens de erro para cada controle sem qualquer marcação personalizada.
  • 🔘 Feedback sobre o envio: O botão Ladda exibe um indicador de carregamento enquanto o envio está em andamento, sinalizando o progresso para o usuário.

Validação de formulário em AngularJS

Validação de formulário Em AngularJS, a validação é o processo de garantir que os dados inseridos em um formulário estejam corretos e completos. Quando um usuário envia o formulário, a validação ocorre antes que os dados sejam enviados ao servidor. O processo de validação garante, da melhor forma possível, que os campos de entrada foram preenchidos corretamente.

Num exemplo prático, imagine um site que exige o preenchimento de um formulário de cadastro antes de conceder acesso completo. A página de cadastro teria campos para nome de usuário, senha, endereço de e-mail e assim por diante.

Por exemplo, o endereço de e-mail precisa sempre estar no formato nomedeusuário@site.domínioSe alguém inserir apenas o nome de usuário, a validação deverá falhar. A validação realiza essas verificações básicas antes que os dados sejam enviados ao servidor para processamento posterior.

⚠️ Nota sobre a versão: O AngularJS (versão 1.x) chegou ao fim de seu ciclo de vida em 31 de dezembro de 2021 e não receberá mais atualizações de segurança. As técnicas descritas abaixo ainda são válidas para aplicações legadas; o Angular moderno realiza a mesma tarefa com formulários baseados em templates ou reativos.

Validação de formulário usando HTML5

A validação de formulários é o processo de pré-validar as informações inseridas em um formulário web antes de serem enviadas ao servidor. Validar no lado do cliente é preferível, pois adiciona muito menos sobrecarga do que apresentar o formulário novamente após uma requisição ao servidor.

O exemplo abaixo mostra um formulário de cadastro simples no qual o usuário insere um nome de usuário, senha, endereço de e-mail e idade. O formulário possui controles de validação que garantem que as informações sejam inseridas corretamente.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
</head>
<body ng-app="sampleApp">
<h1>Guru99 Global Event</h1>

<form>
    Enter your user name:
    <input type="text" name="name" required><br><br>

    Enter your password:
    <input type="password" name="password"><br><br>

    Enter your email:
    <input type="email" name="email"><br><br>

    Enter your age:
    <input type="number" name="age"><br><br>

    <input type="submit" value="Submit">
</form>
</body>
</html>

⚠️ Correções aplicadas a todos os anúncios desta página. Os originais declararam chrset="UTF 8", que não é um atributo válido nem uma codificação válida, e carregou o AngularJS três vezes — angular-route.js primeiro, que gera um erro porque o módulo de roteamento se registra em um framework que não foi carregado, depois angular.min.js e angular.js, a mesma biblioteca duas vezes. Eles também puxaram bootstrap.css através de uma abordagem <script> tag, portanto nenhum estilo foi aplicado. Cada listagem agora carrega uma biblioteca, versão 1.8.3, e vincula a folha de estilo corretamente. O espaçamento do layout é construído a partir de repetições. &nbsp; As entidades foram removidas.

Code Explicação

  1. Para o tipo de entrada de texto, o required O atributo significa que a caixa de texto não pode estar vazia quando o formulário for enviado.
  2. O próximo tipo de entrada é senha. Como o tipo está marcado como senha, o texto inserido no campo fica mascarado.
  3. Como o tipo de entrada foi especificado como e-mail, o texto na caixa deve corresponder ao padrão. nome@site.domínio.
  4. Quando o tipo de entrada está marcado como número, os caracteres digitados pelo teclado simplesmente não são aceitos pelo campo.

saída

Para ver a validação em ação, clique em Enviar sem digitar nada.

Aparece uma janela pop-up informando que o campo precisa ser preenchido, portanto, o controle marcado como obrigatório bloqueia o envio quando está vazio.

Ao inserir um valor no campo de senha, o símbolo '*' é exibido, ocultando os caracteres.

Ao inserir um endereço de e-mail inválido e clicar em Enviar, uma janela pop-up solicita o símbolo @. Por fim, os caracteres digitados no campo de idade nunca aparecem, pois o campo aceita apenas números.

Os pop-ups do navegador são rápidos de configurar, mas seu texto e estilo não podem ser alterados. É aí que entram as propriedades de validação do AngularJS.

Validação de formulário usando $dirty, $valid, $invalid, $pristine

AngularJS Fornece suas próprias propriedades para validação. As seguintes propriedades são expostas em cada controle nomeado:

  • $sujo – O usuário interagiu com o controle
  • $válido – O conteúdo do campo é válido
  • $inválido – O conteúdo do campo é inválido
  • $ impecável – O usuário ainda não interagiu com o controle

A seguir estão os passos para realizar a validação em AngularJS.

Passo 1) Use o novalidate A propriedade é definida ao declarar o formulário. Isso informa ao navegador que a validação será feita pelo AngularJS.

Passo 2) Certifique-se de que o formulário tenha um nome definido, pois esse nome é usado para acessar o estado de validação.

Passo 3) Certifique-se de que cada controle também tenha um name atributo, pelo mesmo motivo. Um controle sem nome nunca é registrado no formulário.

Passo 4) Use o ng-show diretiva para verificar as propriedades $dirty, $invalid e $valid.

O exemplo abaixo possui um único campo de texto no qual o usuário insere o nome de um tópico. Se o campo for deixado em branco, um erro de validação será acionado e a mensagem será exibida.

<form ng-app="DemoApp" ng-controller="DemoController"
      name="myForm" novalidate>
    <p>Topic Name:<br>
        <input type="text" name="user" ng-model="user" required>

        <span style="color:red"
              ng-show="myForm.user.$dirty && myForm.user.$invalid">
            <span ng-show="myForm.user.$error.required">Username is required</span>
        </span>
    </p>
    <p>
        <input type="submit" ng-disabled="myForm.$invalid">
    </p>
</form>

<script>
    var app = angular.module("DemoApp", []);

    app.controller("DemoController", function($scope) {
        // Seed the textbox so the form starts in a valid state
        $scope.user = "AngularJS";
    });
</script>

⚠️ Dois erros de lógica corrigidos. O original desativou o botão com ng-disabled="myForm.user.$dirty && myForm.user.$invalid". Porque $dirty é falso até que o usuário toque no campo; o botão permanece pressionado. habilitado em um formulário vazio e intocado, exatamente o caso que deveria bloquear; myForm.$invalid Abrange ambos. O original também envolvia o valor padrão em $scope.Display = function () { $scope.user = 'Angular'; }, uma função que nunca foi chamada, então a caixa de texto abriu vazia apesar do texto afirmar que mostrava “AngularJS”. A atribuição agora é feita diretamente, com o valor entre aspas do texto circundante.

Code Explicação

  1. O formulário recebeu o nome “myForm”. Isso é necessário para acessar seus controles de validação.
  2. O novalidate A propriedade impede que o navegador faça a validação, permitindo que o AngularJS a execute em seu lugar.
  3. A diretiva ng-show verifica as propriedades “$dirty” e “$invalid”. Se a caixa de texto foi modificada, $dirty é verdadeiro; se o seu valor estiver vazio, $invalid é verdadeiro. Quando ambas são verdadeiras, o elemento span com o texto em vermelho é exibido.
  4. A verificação aninhada lê a propriedade “$error.required”, que é verdadeira sempre que um controle obrigatório não tiver valor, e exibe “O nome de usuário é obrigatório”.
  5. O botão de envio está desativado. ng-disabled sempre que o formulário como um todo for inválido.
  6. O controlador define o valor inicial da caixa de texto como “AngularJS”, para que o formulário seja aberto em um estado válido e a validação seja mais fácil de observar à medida que o texto é apagado.

saída

Quando o formulário é exibido pela primeira vez, a caixa de texto mostra "AngularJS" e o botão de envio está habilitado. Assim que o texto é removido, a mensagem de erro aparece e o botão é desabilitado.

A captura de tela acima mostra duas coisas:

  • O botão de envio está desativado.
  • Não há nome de tópico na caixa de texto Tópico, portanto, a mensagem de erro "Nome de usuário obrigatório" é exibida.

Como exibir erros de validação com ngMessages

O padrão acima funciona, mas não é escalável. Um campo com quatro restrições precisa de quatro restrições aninhadas. ng-show intervalos, e quando vários deles falham ao mesmo tempo, todas as mensagens aparecem juntas. ngMessages O módulo, fornecido separadamente pela equipe do AngularJS, resolve ambos os problemas: ele exibe uma mensagem por vez, na ordem em que as mensagens são escritas.

Carregue o módulo e adicione-o como uma dependência.

<script src="https://code.angularjs.org/1.8.3/angular-messages.js"></script>
<script>
    angular.module("DemoApp", ["ngMessages"]);
</script>

A marcação passa então a ser lida como uma lista de regras em vez de uma pilha de condições.

<input type="text" name="user" ng-model="user"
       required ng-minlength="4" ng-maxlength="20">

<div style="color:red" ng-messages="myForm.user.$error"
     ng-if="myForm.user.$dirty">
    <div ng-message="required">A topic name is required</div>
    <div ng-message="minlength">Use at least 4 characters</div>
    <div ng-message="maxlength">Use no more than 20 characters</div>
</div>

Três detalhes fazem com que isso funcione bem na prática. O ng-messages O atributo aponta para o controle. $error em vez de um booleano, portanto nenhuma condição precisa ser repetida. Apenas a primeira correspondência. ng-message renderiza, o que significa que um campo em branco reporta que é obrigatório em vez de também reclamar sobre seu comprimento. Adicionando ng-messages-multiple Inverte esse comportamento quando cada falha realmente precisa ser listada.

Embrulheping o bloco em ng-if="myForm.user.$dirty" Mantém o formulário silencioso até que o usuário tenha digitado algo. Substituindo $touched pela $dirty Isso atrasa ainda mais a mensagem, até que o foco saia do campo, o que geralmente é a opção mais amigável em um formulário de inscrição longo.

Uma ressalva: ngMessages Como os arquivos são enviados separadamente, esquecer a tag de script ou a dependência do módulo faz com que o bloco não renderize nada, sem nenhum erro no console para explicar o problema.

Escrever mensagens à mão é preciso, mas repetitivo. A próxima seção aborda um módulo que as gera automaticamente.

Validação de formulário usando AngularJS Auto Validate

O AngularJS pode validar automaticamente todos os controles de um formulário, sem a necessidade de código personalizado para a validação ou para as mensagens de erro. Isso é possível graças à inclusão de um módulo da comunidade chamado "jcs-autoValidate".

Com este módulo instalado, não é necessário nenhum código especial para executar a validação ou exibir as mensagens; tudo é tratado internamente pelo jcs-autoValidate.

O exemplo abaixo apresenta um formulário simples com um único campo de texto obrigatório. Uma mensagem de erro é exibida caso o campo não seja preenchido.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/jcs-auto-validate.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp">
    <form name="myForm" novalidate>
        <div class="form-group">
            <label for="user">Topic Name:</label>
            <input class="form-control" type="text"
                   id="user" name="user" ng-model="user" required>
        </div>
        <div class="form-group">
            <input type="submit">
        </div>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['jcs-autoValidate']);
</script>
</body>
</html>

⚠️ Correção: o original identificou o controle com id="user" somente. O jcs-autoValidate acessa o controle através do formulário, portanto, um name O atributo é obrigatório e a mensagem nunca apareceu sem ele. O original também carregava duas versões diferentes do AngularJS, 1.6.4 do Google CDN junto com 1.6.9, e nunca vinculado Bootstrap embora o exemplo dependa de seu form-group e form-control classes para posicionar o texto de erro.

💡 Nota: jcs-autoValidate é um projeto da comunidade e não recebe mais manutenção ativa. Ele ainda pode ser usado em aplicações AngularJS existentes, mas o recurso integrado de validação não está mais disponível. ngMessages A abordagem mostrada anteriormente é a escolha mais segura para qualquer novidade.

Code Explicação

  1. O script “jcs-auto-validate.js”, que contém toda a funcionalidade de validação automática, está incluído.
  2. Cada controle e sua div envolvente são colocados dentro de uma classe “form-group”, que é onde o módulo injeta sua mensagem.
  3. O controle carrega um ID e um name e Bootstrap fornece o form-control estilo.
  4. O módulo “jcs-autoValidate” está listado como uma dependência do módulo AngularJS.

saída

Por padrão, o formulário é exibido exatamente como está escrito.

Ao enviar o formulário vazio, é exibida a mensagem "Este campo é obrigatório", gerada inteiramente pelo jcs-autoValidate. Após a validação do formulário, resta saber o que o usuário vê durante o envio.

Feedbacks de usuários com botões Ladda

Os botões “Ladda” são uma estrutura construída sobre JavaScript Isso confere aos botões um efeito visual quando são pressionados.

Se um botão receber o atributo “ladda” e for pressionado, um efeito de rotação será exibido. Diferentes estilos de dados estão disponíveis para efeitos visuais adicionais.

O exemplo abaixo mostra um formulário simples com um botão de envio. Ao pressionar o botão, um efeito de rotação aparece sobre ele.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/angular-ladda.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp" ng-controller="DemoController">
    <form name="myForm" novalidate ng-submit="submit()">
        <button class="btn btn-primary" type="submit"
                ladda="submitting" name="sbutton"
                data-style="expand-right">Submit</button>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['angular-ladda']);

    app.controller('DemoController', function($scope) {
        $scope.submitting = false;

        $scope.submit = function() {
            $scope.submitting = true;
        };
    });
</script>
</body>
</html>

⚠️ Correção: o original carregado angular-ladda.js e angular-ladda.min.js juntos, o que registra o mesmo módulo duas vezes e, novamente, puxa duas versões do AngularJS. Também listou jcs-autoValidate como uma dependência que este exemplo nunca usa. Uma cópia de cada biblioteca é carregada aqui.

Code Explicação

  1. O "ng-enviarA diretiva “ladda” chama uma função chamada “submit”, que altera o atributo ladda do botão.
  2. O atributo `ladda` pertence ao framework Ladda e é o que adiciona o efeito de rotação. Seu valor está vinculado ao... submitting variável.
  3. A propriedade data-style é outro atributo do Ladda que seleciona um efeito visual diferente.
  4. O módulo 'angular-ladda' precisa ser adicionado à aplicação AngularJS para que o framework funcione.
  5. O submitting A variável é inicializada com o valor falso, portanto o botão inicia sem o efeito de rotação.
  6. A função de envio define submitting para verdadeiro, o que aplica o efeito. Em uma aplicação real, seria redefinido para falso assim que o servidor respondesse; caso contrário, o botão ficaria girando indefinidamente.

saída

Quando o formulário é exibido pela primeira vez, o botão de envio é mostrado em sua forma simples.

Quando o botão é pressionado, o submitting A variável é definida como verdadeira. Esse valor chega ao atributo “ladda” do botão, produzindo o efeito de giro.

Perguntas Frequentes

A variável `$dirty` torna-se verdadeira quando o valor muda. A variável `$touched` torna-se verdadeira quando o campo perde o foco. Use `$touched` para atrasar um erro até que o usuário tenha passado para a próxima etapa, o que parece menos agressivo enquanto tenta corrigir o erro.ping.

Adicione a diretiva ng-pattern com uma expressão regular, por exemplo ng-pattern=”/^[0-9]{6}$/”. A falha então aparece como $error.pattern, que o ngMessages pode relatar como qualquer restrição integrada.

Sim. As ferramentas de IA leem a marcação e geram os blocos correspondentes necessários, como ng-pattern e ngMessages. Sempre revise as expressões regulares, pois os padrões de e-mail e telefone gerados frequentemente rejeitam entradas válidas.

Os assistentes de IA verificam rapidamente as três causas mais comuns: a ausência do atributo name no formulário ou controle, a ausência do ng-model e a omissão do novalidate, o que faz com que o navegador intercepte o envio primeiro.

Não. Isso melhora a experiência e reduz as requisições ao servidor, mas qualquer pessoa pode contornar isso com ferramentas de desenvolvedor. Cada regra aplicada no navegador precisa ser aplicada novamente no servidor.

Resuma esta postagem com: