当前位置: 代码迷 >> JavaScript >> 如果多个元素使用相同的自定义验证指令,如何验证表单?
  详细解决方案

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

热度:54   发布时间:2023-06-13 11:37:54.0

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

我的意思是我对form.startDate元素收到minDate验证错误,而不是仅对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);
            };
        }
    };
}])

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

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

.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 这将被视为...

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

另外,请探索博客中的用法,涵盖如何在您的范围内使用@字符vs. =传递{{ interpolated }}值。 只是...

  • @用于将字符串值传递给指令
  • =用于创建与传递给指令的对象的双向绑定
  • &允许将外部函数传递到指令中并调用
  相关解决方案