2

I have a async validation directive which works fine when, but it depends on two fields to define if a person exists (numId and type), here's the code:

app.directive('personaUnica', function($http, $q){
return{
    require:'ngModel',
    scope: {
        tipo: "=personaUnica"
    },
    link: function(scope, element, attrs, ctrl){
        ctrl.$asyncValidators.personaUnica = function(modelValue, viewValue){
            if (ctrl.$isEmpty(modelValue)) {
                 // valido si es vacio
                 return $q.when();
            }
            var defer = $q.defer();
            $http.get('/someRESTEndpoint/', {
                params:{ identificacion: modelValue, tipo: scope.tipo }     
            }).then(function(respuesta){
                //Person found, not valid
                if( respuesta.data.elementoExiste ){                        
                    defer.reject('Persona existe.');
                }   
            }, function(respuesta){
                //Person not found, resolve promise
                if(!respuesta.data.elementoExiste){
                    defer.resolve();
                }                       
            });

            return defer.promise;
        }
    }
}
});

But I dont know how to make the same validation when the other dependant field has changed.

I've read something about require ^form in the directive but in kinda lost.

I've tried to add this block of code

            scope.$watch('tipo', function(){
            ctrl.$validate();   
        }); 

But then I get an infinite $digest loop.

Thanks in advance.

raav6
  • 131
  • 2
  • 10
  • I found that validators are firing on the form's Load, not when the value is changing. Have you figured out how to only fire them when you change value? See my question https://stackoverflow.com/questions/46101820/do-asyncvalidators-fire-all-the-time – Naomi Sep 07 '17 at 20:45

2 Answers2

0

You can do something like this:

$scope.$watch('tipo', function(newValue, oldValue, scope) {
        if (newValue != oldValue) {
         ctrl.$validate();   
        }
});

This way, $scope.watch will be called everytime you have a new value on your $scope.tipo.

0

Turns out that I was using watch in the wrong place inside the ctrl.$asyncValidators.numId, it has to be outside. Now It works as expected.

app.directive('numId', function($http, $q){
return {
    restrict : 'A',
    scope: {
        tipo: "=numId"
    },
    require: 'ngModel',
    link: function(scope, element, attrs, ctrl){
        ctrl.$asyncValidators.numId = function(modelValue, viewValue){              
            if (ctrl.$isEmpty(modelValue) || ctrl.$isEmpty(scope.tipo)) {
              // consider empty model valid
              console.log('Not going yet..');
              return $q.when();
            }

            var defer = $q.defer();

            $http.get("/some-server/endpoint",{
                params:{ identificacion: modelValue, tipo: scope.tipo }     
            }).then(function(res){                                      
                if( res.data.personaExiste){
                    console.log('exists, not valid')                        
                    defer.reject('exists, not valid');
                }else if( !res.data.personaExiste ){
                    console.log('NOT exists, valid!')                       
                    defer.resolve();
                }   
            }, function(){
                defer.reject('Error...');
            });

            return defer.promise;                   
        }

        // Search when tipo is changed
        scope.$watch('tipo', function(){
            console.log('Tipo:' + scope.tipo)       
            ctrl.$validate();   
        });             
    }
}
});

And the html:

<div class="form-group">
   <label>Numero identificacion</label>
   <input type="text" 
          name="numId"
          required
          ng-model="busqueda.numId"                     
          num-id="busqueda.tipoUsuario">
    <pre class="well"> {{ frmBuscar.numId.$error }} </pre>
</div>
raav6
  • 131
  • 2
  • 10