Skip to content

401 Validation Directive

zarlex edited this page Mar 6, 2017 · 1 revision

Validation Directive

We are building a directive and use the AngularJS validation pipeline to register our custom validation logic. In order to check if the hero name already exist we will use the HeroesCollection to get all existing heroes.

Directive

Create the folder directives in the folder modules/hero and create the file hero-validate-unique.directive.js.

angular.module('mwPortal.Hero')
  .directive('heroValidateUnique', function (HeroesCollection) {
    return {
      require: 'ngModel',
      scope: {
        validate: '=heroValidateUnique'
      },
      link: function (scope, elm, attr, ngModel) {
        var heroes = new HeroesCollection();
        var validateHero = function (value) {
          return value && value.length && (angular.isUndefined(scope.validate) || scope.validate);
        };

        // we are registering a new validate that will be executed by angular on ngModel changes
        ngModel.$validators.heroUnique = function (value) {
          if (validateHero(value)) {
            var existingHero = heroes.findWhere({name: value});
            return !existingHero;
          } else {
            return true;
          }
        };

        heroes.fetch().then(function () {
          // trigger a validation after the heroes are fetched
          ngModel.$validate();
        });
      }
    };
  });

To use the AngularJS validation pipeline we require ngModel. To register a new validator we just a new key to the $validators object that has a function as value.

The function will be called on every ngModel change. You can also trigger it manually by calling ngModel.$validate(). When the function returns false the ngModel will be come invalid. more information

In our function we simply check if the HeroesCollection has a hero with the name of the current ngModel value. When there is a hero in the collection with that name the function returns false and therefor the whole ngModel becomes invalid.

Include the directive in your index.html

...
<!-- Hero module -->
...
<script src="app/modules/hero/directives/hero-validate-unique.directive.js"></script>
...

Use directive

Open the file _form.template.html in the folder hero/templates and add the directive hero-validate-unique to the input field of the hero name

<input name="name"
       type="text"
       ng-model="name"
       mw-model="ctrl.hero"
       hero-validate-unique="ctrl.hero.isNew()"
       required>

When you edit a hero the name will always exist because it is already in the server database. That is why we set as condition that the hero name should be only validated when it is a new hero.

The method isNew() is a BackboneJS method that will return true as long the model has no id

Clone this wiki locally