In below form I'm checking that an e-mail address is required :

http://jsfiddle.net/U3pVM/16994/

I want to extend the validation so that it check that the first two characters begin with 'DD' . It seems I need to add a custom directive but I'm unsure how to link the e-mail fields with the directive ?

fiddle code :

<form ng-app="myApp" ng-controller="validateCtrl" 
name="myForm" novalidate>

<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
</span>
</p>

<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||  
myForm.email.$dirty && myForm.email.$invalid">
</p>

</form>

var app = angular.module('myApp', []);
app.controller('validateCtrl', function($scope) {

});

app.directive("myValidator", function(){
          // requires an isloated model
          return {
           // restrict to an attribute type.
           restrict: 'A',
          // element must have ng-model attribute.
           require: 'ngModel',
           link: function(scope, ele, attrs, ctrl){

              // add a parser that will process each time the value is
              // parsed into the model when the user updates it.
              ctrl.$parsers.unshift(function(value) {
                if(value){
                  // test and set the validity after update.
                  var valid = value.charAt(0) == 'D' && value.charAt(1) == 'D';
                  ctrl.$setValidity('invalidAiportCode', valid);
                }

                return valid ? value : undefined;
              });

           }
          }
       });
share
    
It seems like you did most of it correctly (at least, I didn't find any obvious errors), but you didn't apply the directive to your input, e.g. <input ng-model="email" my-validator> (if it applies to the email field). And if you are using later versions of Angular, you can just use ctrl.$validators.invalidAirportCode = function(){ } and return true/false instead of $parser – New Dev Jul 7 '15 at 17:47

Here's how I would do it, using an authentication example:

The simple markup:

<input type="email" ng-model="existingUser.email">
<button ng-click="login(existingUser)">Login</button>

The controller:

auth.controller('AuthCtrl', '$scope', 'validation', function($scope, validation) {

  $scope.existingUser = {
    email: '',
    password: ''
  }

  $scope.login = function() {

    validation.validateSignin($scope.existingUser)
      .catch(function(err) {

        // The validation didn't go through,
        // display the error to the user 
        $scope.status.message = err;
      })
      .then(function(res) {

        // Validation passed
        if (res === true) {

          // Do something
        }
    });
  }
}

The factory:

auth.factory('validation', ['$q', function($q) {
  return {
    validateSignin: function(existingUser) {

      var q = $q.defer();

      if (existingUser.email.substring(0,2) !== 'DD') {
        q.reject('The email must start with "DD"');
      }

      q.resolve(true);

      return q.promise;
    }
  }
}]);

Let me explain what's happening, first I'm creating a factory which will carry out the validation. Then I'm creating a promise with a resolve and a reject method, the reject method will be called if the validation failed, and if it succeeded then the resolve will be called. Then in your controller you can do things based on the outcome.

Let me know if anything is unclear.

share

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.