AngularJS 1.3: Conhecendo os validadores assíncronos

O que são os $asyncValidators?

Os $asyncValidators, como o nome já diz, são validadores assíncronos, ou seja, eles não são executados pelo Angular de forma independente. Eles representam um dos componentes do NgModelController que é o controlador da diretiva mais usada no mundo do AngularJS, o ngModel.

Onde eu deveria utilizar um validador assíncrono?

Você deve utilizar validadores assíncronos junto ao ngModel (obviamente), em um campo de texto em que deverá ser digitado um nome de usuário, um endereço de correio eletrônico etc.

Como ele funciona?

Dentro de cada validador, deverá ter uma promessa, que deverá retornar um resolve ou um reject. Caso retorne um resolved, o campo será definido como válido, caso retorne um reject, o campo será definido como inválido.

Quando o validador for definido como inválido, será adicionada uma nova classe chamada ng-(nome desnormalizado do seu validador)-invalid ou com o final -valid , caso ele seja definido como válido.

Enquanto o seu formulário tiver algum validador pendente, o FormController equivalente receberá a chave $pending , assim como o campo equivalente dentro do FormController (exemplo: form.email.$pending ou form.$pending ), equivalente também receberá.

O campo só será definido como válido ou inválido, quando todos os validadores assíncronos forem resolvidos. Enquanto isso a chave $pending continuará a existir no campo e no formulário.

Você também pode verificar se o seu campo é válido ou inválido atráves de uma chave dentro da chave $error, que se encontra dentro do FormController atual. Exemplo:

<form name="myForm">
  <div ng-show="myForm.$pending">
    Verificando...
  </div>
  <input ng-model="user.email" unique-email>
  <div ng-show="myForm.email.$pending.uniqueEmail">
    Verificando...
  </div>
  <div ng-show="myForm.email.$error.uniqueEmail">
    Este e-mail já está sendo usado por outra pessoa.
  </div>
</form>

Dessa maneira, você poderá implementar vários validadores assíncronos dentro de um só NgModelController . Veja a próxima seção e entenderá melhor.

Como utilizar?

Você deve aprender a utilizar a opção require do $compile, que importará o NgModelController da diretiva atual para que você possa inserir o seu validador assíncrono. O seu validador será definido por uma nova chave em NgModelController.$asyncValidators, a chave deverá ser o nome do seu validador.

Exemplo

.directive('uniqueUsername', function ($http, $q) {
   return {
     require: '?ngModel',
     link: function (scope, element, attrs, ngModel) {
       ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
         var value = modelValue || viewValue;

         // Procura por um usuário pelo nome
         return $http.get('/api/users/' + value).then(function resolved() {
           return $q.reject('exists');
         }, function rejected() {
           return true;
         });
       };
     }
  };
});

Espero que tenham gostado, quaisquer dúvidas, deixem seus comentários.