最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angularjs initial form validation with directives - Stack Overflow

programmeradmin2浏览0评论

I have a validation directive called valid-number that is used to set the validity of a form using $setValidity - this works fine for any text values that I type into the input box that have the directive applied to as an attribute.

The HTML is

<form name="numberForm">
<input name="amount" type="text" ng-model="amount" required  valid-number /></form>

The directive is as follow

angular.module('test',[]).directive('validNumber',function(){
            return{
                require: "ngModel",
                link: function(scope, elm, attrs, ctrl){

                    var regex=/\d/;
                    ctrl.$parsers.unshift(function(viewValue){
                        var floatValue = parseFloat(viewValue);

                        if(regex.test(viewValue)){
                            ctrl.$setValidity('validNumber',true);
                        }
                        else{
                            ctrl.$setValidity('validNumber',false);
                        }
                        return viewValue;
                    });
                }
            };
        });

However, I would also like the validation to be triggered and set the css to an invalid clsss if the value the input box is initialised to when the page is first loaded is invalid, eg if I set $scope.amount = 'not a number' I would expect the input box to have had the directive applied to it, but no joy. In order for not a number to be highlighted as invalid I have to make a change to the contents of the input, which triggers the directive.

How can I ensure the directive applies to whatever the <input> is initialised with?

A full code example is here;

/

I have a validation directive called valid-number that is used to set the validity of a form using $setValidity - this works fine for any text values that I type into the input box that have the directive applied to as an attribute.

The HTML is

<form name="numberForm">
<input name="amount" type="text" ng-model="amount" required  valid-number /></form>

The directive is as follow

angular.module('test',[]).directive('validNumber',function(){
            return{
                require: "ngModel",
                link: function(scope, elm, attrs, ctrl){

                    var regex=/\d/;
                    ctrl.$parsers.unshift(function(viewValue){
                        var floatValue = parseFloat(viewValue);

                        if(regex.test(viewValue)){
                            ctrl.$setValidity('validNumber',true);
                        }
                        else{
                            ctrl.$setValidity('validNumber',false);
                        }
                        return viewValue;
                    });
                }
            };
        });

However, I would also like the validation to be triggered and set the css to an invalid clsss if the value the input box is initialised to when the page is first loaded is invalid, eg if I set $scope.amount = 'not a number' I would expect the input box to have had the directive applied to it, but no joy. In order for not a number to be highlighted as invalid I have to make a change to the contents of the input, which triggers the directive.

How can I ensure the directive applies to whatever the <input> is initialised with?

A full code example is here;

http://jsfiddle.net/JW43C/5/

Share Improve this question asked Jun 9, 2013 at 15:41 GrahamBGrahamB 5691 gold badge6 silver badges19 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 16

$parsers array contains a list of functions that will be applied to the value that model receives from the view (what user types in), and $formatters array contains the list of functions that are being applied to the model value before it's displayed in the view.

In your directive you correctly used the $parsers array, but you also need to add the $formatters array if you want the initial value to be validated:

angular.module('test',[]).directive('validNumber',function(){
  return{
    require: "ngModel",
    link: function(scope, elm, attrs, ctrl){
      var regex = /^\d$/;
      var validator = function(value){
        ctrl.$setValidity('validNumber', regex.test(value));
        return value;
      };

      ctrl.$parsers.unshift(validator);
      ctrl.$formatters.unshift(validator);
    }
  };
});

Demo plunker

You can simply call your verification function during the linking phase, like in this fiddle :

link: function(scope, elm, attrs, ctrl) {                       
    var regex=/\d/;
    var verificationFunction = function(viewValue) {
        var floatValue = parseFloat(viewValue);

        if(regex.test(viewValue)) {
            ctrl.$setValidity('validNumber',true);
            return viewValue;
        }
        else {
            ctrl.$setValidity('validNumber',false);
            return undefined;
        }
    };

    ctrl.$parsers.unshift(verificationFunction);
    verificationFunction();
}

After (>=) angular 1.3.1 version was released you could implement that behaviour with a little bit correct way, following angular validation directives style (e.g. required, maxlength).

In that case you have to append your validator as property of $validators array and there are no need in $parsers or $formatters anymore:

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

app
  .directive('validNumber', function() {
    return {
      require: "ngModel",
      link: function(scope, elm, attrs, ctrl) {
        var regex = /^\d+$/;

        ctrl.$validators['validNumber'] = function(modelValue, viewValue) {
          return regex.test(viewValue);
        };
      }
    };
  });

app.controller('NumberCtrl', NumberCtrl);

function NumberCtrl($scope) {
  $scope.amount = '5z';
};
input.ng-invalid {
  background-color: #FA787E;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>

<div ng-app="test">
  <div ng-controller="NumberCtrl">

    <div ng-form name="numberForm">
      <input name="amount"
             type="text"
             ng-model="amount"
             required 
             valid-number />
      
      <span ng-show="numberForm.amount.$error.validNumber">
        Doesn't look like an integer
      </span>
    </div>        
  </div>
</div>

发布评论

评论列表(0)

  1. 暂无评论