Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I need to create a validation directive for showing all input errors for each input automatically. This validation directive should show all errors at current moment and list of errors should be updated automatically while user is typing.

I need to show all errors for input if input is dirty, not empty and invalid. I need to add all errors into html element near this input element.

For example if input have type="email" and ng-minlength="5" and user typed 'abc' I need to show such errors near this input: 'Invalid email; Please enter at least 5 characters;'

For example if input has type="number" attr and min="200" and min-model="minnumber" and minnumber model set to '300' and user typed '100' I need to show such errors near this input: 'Please enter the minimum number of 500; Should be greater than Min Number;'

Also I need to update all errors messages for input in prev example if related model (min-model param) is updated.

var app = angular.module('app', []);

app.controller('appCtrl', function ($scope) {

});

app.directive('validate', function () {
    return {
        restrict: 'A',
        require: 'ngModel', // require:  '^form',

        link: function (scope, element, attrs, ctrl) {
            console.log('======================');
            console.log(scope);
            console.log(element);
            console.log(attrs);
            console.log(ctrl);
            console.log(scope.form.$error);
            angular.forEach(scope.form.$error, function (value, key) {
                console.log('scope.form.$error = ' + key + ': ' + value);
                console.log(value);
            });

        }
    };
});


app.directive('positiveInteger', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                var INTEGER_REGEXP = /^\d+$/;
                if (INTEGER_REGEXP.test(viewValue)) { // it is valid
                    ctrl.$setValidity('positiveInteger', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('positiveInteger', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('positiveFloat', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                var FLOAT_REGEXP = /^(?:[1-9]\d*|0)?(?:\.\d+)?$/;
                if (FLOAT_REGEXP.test(viewValue)) { // it is valid
                    ctrl.$setValidity('positiveInteger', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('positiveInteger', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('minModel', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (viewValue > scope[attrs.minModel]) { // it is valid
                    ctrl.$setValidity('minModel', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('minModel', false);
                    return undefined;
                }
            });

        }
    };
});

Can you help to make this validation directive?

Or maybe can you point me into the right direction?

Link to JSFiddle with some code for testing.

P.S. Something similar is made with UI-Utils but their directive does not give ability to set similar error messages in one place.

share|improve this question
    
This is exactly why I created this open source module jonsamwell.github.io/angular-auto-validate the rational behind it is in my blog post jonsamwell.com/dynamic-angularjs-validation –  Jon Samwell Aug 18 at 14:46

2 Answers 2

I want to suggest look at this post in this post author is explaining how to achieve your goals , and you can deeply dive into the code . link

example from this post showing error messages

module = angular.module('app', []);

module.directive('showErrors', function($timeout) {
    return {
      restrict: 'A',
      require: '^form',
      link: function (scope, el, attrs, formCtrl) {
        // find the text box element, which has the 'name' attribute
        var inputEl   = el[0].querySelector("[name]");
        // convert the native text box element to an angular element
        var inputNgEl = angular.element(inputEl);
        // get the name on the text box
        var inputName = inputNgEl.attr('name');

        // only apply the has-error class after the user leaves the text box
        var blurred = false;
        inputNgEl.bind('blur', function() {
          blurred = true;
          el.toggleClass('has-error', formCtrl[inputName].$invalid);
        });

        scope.$watch(function() {
          return formCtrl[inputName].$invalid
        }, function(invalid) {
          // we only want to toggle the has-error class after the blur
          // event or if the control becomes valid
          if (!blurred && invalid) { return }
          el.toggleClass('has-error', invalid);
        });

        scope.$on('show-errors-check-validity', function() {
          el.toggleClass('has-error', formCtrl[inputName].$invalid);
        });

        scope.$on('show-errors-reset', function() {
          $timeout(function() {
            el.removeClass('has-error');
          }, 0, false);
        });
      }
    }
  });

module.controller('NewUserController', function($scope) {
  $scope.save = function() {
    $scope.$broadcast('show-errors-check-validity');

    if ($scope.userForm.$valid) {
      alert('User saved');
      $scope.reset();
    }
  };

  $scope.reset = function() {
    $scope.$broadcast('show-errors-reset');
    $scope.user = { name: '', email: '' };
  }
});
share|improve this answer

all input errors for each input automatically

Personally, I see more cons than pros from that phrase.

Number one, you are hiding your error messages in javascript from html.

  • I think it's better to show as much as possible to users with html in a understandable way,
    and I believe it is the way to go.

Number two, you are adding complexity to any costumed error messages.

  • What if your next developer wants to change error messages to like this, Hey, your input is too short. Do you want him to abandon your general error messages? Or change it in your javascript?

  • What if your next developer add his custom error messages using ng-show.Then, you will have two error messages meaning the same. Then, will you not allow to have that? or, your general directive error message should be hidden? Or, apply that custom error message into general error message? If so, then how? See, itt gets complex.

IMHO, this general error message only works when you are very sure of the following;

  • Error messages looks all the same on many pages.
  • Error messages will not change in any case in the future.
  • html developers should not care about error messages.
  • No custom error message is allowed.

If you are not sure about the above I mentioned, I would recommend not to create a general error messages.

share|improve this answer

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.