Miguel Moura
Miguel Moura

Reputation: 39484

Angular custom validation directive. Get errors from view model

I have the following (https://jsfiddle.net/f30bj43t/5/) HTML:

<div ng-controller="DataController as vm">
  <div ng-repeat="name in vm.users track by $index">{{name}}</div>
  <form name="form" validation="vm.errors">
    <input validator ng-model="vm.name" name="vm.name" placeholder="name" type="text" />
    <a href="#" ng-click="vm.add(vm.name)">Add</a>
  </form>
</div>

This form adds names to a list and the controller is:

app.controller("DataController", DataController);

function DataController() {
  var vm = this;
  vm.name = "Mary";
  vm.users = ["Alice", "Peter"];
  vm.errors = [];
  vm.add = function(name) {  
    if (name == "Mary") {
      var error = { property: "name", message: "name cannot be Mary"};
      if (vm.errors.length == 0) 
        vm.errors.push(error);        
      } else {
        vm.users.push(name);      
        vm.errors = [];
      }      
    }
}

On the form I added validation="vm.errors" that defines which variable holds the errors to be used in each validator directive ...

Then in each validator directive I will use that variable to pick the correct error and display it ...

app.directive("validation", validation);

function validation() {

  var validation = {
    controller: ["$scope", controller],
    replace: false,
    restrict: "A",
    scope: {
      validation: "="
    }
  };

  return validation;

  function controller($scope) { 
    this.getErrors = function () {
      return $scope.validation;
    }    
  } 

}  

app.directive("validator", validator);

function validator() {

  var validator = {
    link: link,
    replace: false,
    require: "^validation",
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes, controller) {    
    var errors = controller.getErrors();
    console.log(errors);    
    // do something with errors
  } 

}

PROBLEM

In link function of validator directive I need to track changes of the variable passed by validation="vm.errors" so I can in each validator check if a error occurs and take action.

But console.log(errors) seems to have no effect ...

How can I solve this?

Upvotes: 2

Views: 557

Answers (2)

Gabriel C&#226;mara
Gabriel C&#226;mara

Reputation: 1249

You can do it with either $watch or $broadcast and $on.
I preffer to use the $on, because watching a variable consumes more than listening to an event and I'd say that to your case it's better to use $broadcast and $on, because you're not watching a scope variable, but a variable from a controller.

If you want to learn more about $on and $watch, here's a suggestion: Angular JS $watch vs $on

And here's your JSFiddle with the modifications.

Upvotes: 1

JavierFromMadrid
JavierFromMadrid

Reputation: 621

Here you have a working jsfiddle: https://jsfiddle.net/f30bj43t/8/

I am logging the vm.errors variable into the console each time it changes:

function link(scope, element, attributes, controller) {   
    scope.$watch('vm.errors.length', function () {
        if(scope.vm.errors){
            console.log(scope.vm.errors);
        }   
  });
} 

This is possible due to the scope inheritance. On your case, vm is a variable added to the controller's scope, and all directives inside this scope will inherit it by default (there are ways to avoid that).

Anyhow it seems you are creating too much directives. On your case, for me would be enough having everything in the controller.

Cheers

Javier

Upvotes: 1

Related Questions