如果多个元素使用相同的自定义验证指令,如何验证表单?

时间:2015-07-17 14:25:49

标签: javascript html angularjs validation angularjs-scope

我已经为这种格式MM/YYYY的日期编写了一个验证指令,如果我每页只有一个元素可以验证,那么它很有效,但是当我有多个元素时,我注意到验证是混合的,所以可能是scope误解。

我的意思是minDate元素的form.startDate验证错误,而不仅仅是form.endDate才看到它。

这是我的观点:

<form>
    <input id="start-date"
           type="text"
           validate-short-date
           data-max-date="{{endingDate | toDate:'MM/YYYY':'YYYYMM'}}"
           data-greater-date="{{nextMonth | toDate:'MM/YYYY':'YYYYMM'}}"
           name="startDate"
           data-ng-model="startingDate">

    <input id="end-date"
           type="text"
           validate-short-date
           data-min-date="{{thisMonth | toDate:'MM/YYYY':'YYYYMM'}}"
           name="endDate"
           data-ng-model="endingDate">
</form>

我想使用scope[ngModel.$name],但问题只是部分修复,所以我可能错过了如何使用范围来保持指令划分。

这是指令:

.directive('validateShortDate', ['moment', function(moment) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {

            var pattern, regex;
            pattern = '^((0[0-9])|(1[0-2])|[1-9])\/(19|20)[0-9]{2}$';
            regex = new RegExp(pattern, 'i');

            var isEmpty = function(modelValue){
                return modelValue === '' || modelValue === null || angular.isUndefined(modelValue);
            };

            var toDate = function(modelValue){
                return moment(modelValue, 'MM/YYYY').format('YYYYMM');
            };

            scope[ngModel.$name] = {};
            scope[ngModel.$name].maxDate = false;
            scope[ngModel.$name].minDate = false;
            scope[ngModel.$name].greaterDate = false;
            scope[ngModel.$name].lesserDate = false;

            attr.$observe('maxDate', function() {
                if (!isEmpty(attr.maxDate)) {
                    scope[ngModel.$name].maxDate = attr.maxDate;
                    ngModel.$validate();
                }
            });

            attr.$observe('greaterDate', function() {
                if (!isEmpty(attr.greaterDate)) {
                    scope[ngModel.$name].greaterDate = attr.greaterDate;
                    ngModel.$validate();
                }
            });

            attr.$observe('minDate', function() {
                if (!isEmpty(attr.minDate)) {
                    scope[ngModel.$name].minDate = attr.minDate;
                    ngModel.$validate();
                }
            });

            attr.$observe('lesserDate', function() {
                if (!isEmpty(attr.lesserDate)) {
                    scope[ngModel.$name].lesserDate = attr.lesserDate   ;
                    ngModel.$validate();
                }
            });

            ngModel.$validators.maxDate = function(modelValue) {
                console.log(ngModel.$name);
                var maxDate = scope[ngModel.$name].maxDate;
                if (!isEmpty(modelValue) && !isEmpty(maxDate) && regex.test(modelValue)) {
                    return toDate(modelValue) <= maxDate;
                }
                return true;
            };

            ngModel.$validators.greaterDate = function(modelValue) {
                var greaterDate = scope[ngModel.$name].greaterDate;
                if (!isEmpty(modelValue) && !isEmpty(greaterDate) && regex.test(modelValue)) {
                    return toDate(modelValue) < greaterDate;
                }
                return true;
            };

            ngModel.$validators.minDate = function(modelValue) {
                var minDate = scope[ngModel.$name].minDate || false;
                if (!isEmpty(modelValue) && !isEmpty(minDate) && regex.test(modelValue)) {
                    return toDate(modelValue) >= minDate;
                }
                return true;
            };

            ngModel.$validators.lesserDate = function(modelValue) {
                var lesserDate = scope[ngModel.$name].lesserDate;
                if (!isEmpty(modelValue) && !isEmpty(lesserDate) && regex.test(modelValue)) {
                    return toDate(modelValue) > lesserDate;
                }
                return true;
            };

            ngModel.$validators.valid = function(modelValue) {
                return isEmpty(modelValue) || regex.test(modelValue);
            };
        }
    };
}])

如何在同一视图中保留更多验证指令?

1 个答案:

答案 0 :(得分:0)

您的怀疑是正确的,这是一个范围问题。您希望在这些指令上具有隔离范围。查看this blog post以获取有关此主题的详细信息。关于您的代码,请尝试以下更改...

.directive('validateShortDate', ['moment', function(moment) {
    return {
        restrict: 'A',
        scope: {}, // -- isolate - not shared with parent scope
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
        [...]

此外,如果您希望这些属性作为命名范围属性,那么本文还介绍了执行此操作的技巧。这可以减轻您当前在指令中scope[ngModel.$name]scope.name的解决方法。这将被视为......

scope: {
    'name': '='
    [...] // -- other attributes to be named on scope
}

另请参阅博客中的用法,了解如何在您的范围内使用{{ interpolated }}字符与@传递=值。简单地...

  
      
  • @用于将字符串值传递给指令
  •   
  • =用于创建与传递给指令
  • 的对象的双向绑定   
  • &安培;允许将外部函数传递到指令并调用
  •