以编程方式设置模型值时未触发自定义验证

时间:2014-07-30 12:40:14

标签: angularjs

创建一个自定义验证指令,当输入除数字或空格以外的任何内容时,该指令使输入无效。当我以编程方式将值更改为应通过验证的值时,验证状态不会更改。

检查此JSFIDDLE并亲自查看。有什么想法吗?

<div ng-app="test" ng-controller="Ctrl">
<form name="form">
    <input custom-validation type="text" ng-model="box.text" name="text" />
</form>
<button ng-click="change()">Change to numbers only</button> 
Why doesn't changing to numbers only pass the validation?
</div>

angular.module('test', []);
angular.module('test').directive('customValidation', function () {
    'use strict';
    return {
        require: '?ngModel',
        link: function (scope, element, attrs, ngModelCtrl) {

            ngModelCtrl.$parsers.push(function removeIllegalCharacters(viewValue) {

                if(viewValue === undefined){
                    ngModelCtrl.$setValidity('numbersAndSpacesOnly', true); //empty value is always valid
                } else {
                    var clean = viewValue.replace(/[^0-9 ]+/g, '');
                    if (viewValue === clean) {
                        ngModelCtrl.$setValidity('numbersAndSpacesOnly', true);
                    } else {
                        ngModelCtrl.$setValidity('numbersAndSpacesOnly', false);
                    }
                }

                return viewValue;
            });

        }
    };
});

angular.module('test').controller('Ctrl', function ($scope, $timeout) {
    $scope.change = function () {
        $scope.box.text = '12345';
    }
});

1 个答案:

答案 0 :(得分:3)

ngModel使用2个代码管道(数组)进行验证:

  1. $parsers数组具有在从用户更改时应用于视图值的功能;每个函数都使用前一个返回的值调用,第一个函数用视图值调用,最后一个函数的返回值写在模型中。这通常用于验证和转换用户输入(例如,从input type="text"的文本到数字)。

  2. $formatters数组的工作方式类似,但方向相反。它接收模型值并对其进行转换,最后一个函数的返回值为新视图值。

  3. 两个管道中的功能可以选择调用ngModel.$setValidity()来改变ngModel的有效性状态。

    对于此问题的范围:为了验证模型值,您必须使用$formatters,类似于您已使用的$parsers

    angular.module('test').directive('customValidation', function () {
        'use strict';
        return {
            require: '?ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {
    
                function removeIllegalCharacters(value) {
                    if(value === undefined){
                        ngModelCtrl.$setValidity('numbersAndSpacesOnly', true); //empty value is always valid
                    } else {
                        var clean = value.replace(/[^0-9 ]+/g, '');
                        if (value === clean) {
                            ngModelCtrl.$setValidity('numbersAndSpacesOnly', true);
                        } else {
                            ngModelCtrl.$setValidity('numbersAndSpacesOnly', false);
                        }
                    }
    
                    return value;
                }
    
                ngModelCtrl.$parsers.push(removeIllegalCharacters);
                ngModelCtrl.$formatters.push(removeIllegalCharacters);
            }
        };
    });