使用AngularJS验证具有互斥字段的表单

时间:2021-03-04 11:51:27

I'm creating a web application using AngularJS, and i have a form with two fields that should be validated as mutually exclusive. I mean either one or the other field should be filled, but not both (it is also valid if neither is filled). My form (simplified model of the real case) is like this:

我正在使用AngularJS创建一个Web应用程序,我有一个包含两个字段的表单,应该验证为互斥。我的意思是应该填写一个或另一个字段,但不能同时填充(如果两者都没有填充它也是有效的)。我的表格(真实案例的简化模型)是这样的:

<form id="form1" name="form1">
   <p>
      <input type="text" id="field1" name="field1" ng-model="model.item1" not-both-filled="model.item2" />
   </p>
   <p>
      <input type="text" id="field2" name="field2" ng-model="model.item2" not-both-filled="model.item1" />
   </p>
   <p ng-show="form1.$invalid">not valid</p>
   <p ng-show="!form1.$invalid">valid</p>
</form>

and i created a directive like this:

我创建了一个这样的指令:

angular.module('myApp', []).directive('notBothFilled', function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
            var validateNotBothFilled = function(value) {
                var theOther = scope.$eval(attrs.notBothFilled);
                var isNotValid = (value && value !== '' && theOther && theOther !== '');
                ctrl.$setValidity('field1', !isNotValid);
                ctrl.$setValidity('field2', !isNotValid);
                return value;
            };

            ctrl.$parsers.unshift(validateNotBothFilled);
            ctrl.$formatters.unshift(validateNotBothFilled);

        }
    };
});

However, this has the following problem:

但是,这有以下问题:

  1. fill field 1
  2. 填充字段1
  3. fill field 2
  4. 填充字段2
  5. form becomes invalid
  6. 表格变得无效
  7. empty field 1
  8. 空场1
  9. form should become valid but does not
  10. 表格应该有效但不会

If i empty field2 instead, the behaviour is correct.

如果我改为清空field2,行为是正确的。

Sorry i still have very little AngularJS experience (and Englis is not my native language), but could someone tell me:

对不起,我仍然有很少的AngularJS经验(英语不是我的母语),但有人可以告诉我:

  1. Is directive like this is generally the correct approach to validate mutually exclusive fields in AngularJS?
  2. 像这样的指令通常是验证AngularJS中互斥字段的正确方法吗?
  3. What is wrong with my code, how can i get the form valid again if i empty any of the fields?
  4. 我的代码有什么问题,如果我清空任何字段,如何才能使表单再次有效?

I also have a JS fiddle: http://jsfiddle.net/k6ps/7vCZg/

我也有一个JS小提琴:http://jsfiddle.net/k6ps/7vCZg/

Sincerely, k6ps

真诚的,k6ps

1 个解决方案

#1


2  

Your main problem is these 2 lines:

你的主要问题是这2行:

ctrl.$setValidity('field1', !isNotValid);
ctrl.$setValidity('field2', !isNotValid);

These 2 lines actually set 2 custom validity of the same input field, you need to somehow get the ngModelController of the other input field to set its validity

这2行实际上设置了相同输入字段的2个自定义有效性,你需要以某种方式获取其他输入字段的ngModelController来设置其有效性

Try this:

尝试这个:

<form id="form1" name="form1">
    <p>
        <input type="text" id="field1" name="field1" ng-model="model.item1" not-both-filled="field2" form="form1"/> 
    //I pass the field name instead and also the form where these inputs are defined.
    </p>
    <p>
        <input type="text" id="field2" name="field2" ng-model="model.item2" not-both-filled="field1" form="form1"/>
    </p>
    <p ng-show="form1.$invalid">not valid</p>
    <p ng-show="!form1.$invalid">valid</p>
</form>

JS:

JS:

angular.module('myApp', []).directive('notBothFilled', function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
            var validateNotBothFilled = function(value) {
                var form = scope[attrs.form];
                var theOther = form[attrs.notBothFilled];
                var isNotValid = (value && value !== '' && theOther.$modelValue && theOther.$modelValue !== '');
                ctrl.$setValidity('field', !isNotValid);//set validity of the current element
                theOther.$setValidity('field', !isNotValid);//set validity of the other element.
                return value;
            };

            ctrl.$parsers.unshift(validateNotBothFilled);

        }
    };
});

DEMO

DEMO

#1


2  

Your main problem is these 2 lines:

你的主要问题是这2行:

ctrl.$setValidity('field1', !isNotValid);
ctrl.$setValidity('field2', !isNotValid);

These 2 lines actually set 2 custom validity of the same input field, you need to somehow get the ngModelController of the other input field to set its validity

这2行实际上设置了相同输入字段的2个自定义有效性,你需要以某种方式获取其他输入字段的ngModelController来设置其有效性

Try this:

尝试这个:

<form id="form1" name="form1">
    <p>
        <input type="text" id="field1" name="field1" ng-model="model.item1" not-both-filled="field2" form="form1"/> 
    //I pass the field name instead and also the form where these inputs are defined.
    </p>
    <p>
        <input type="text" id="field2" name="field2" ng-model="model.item2" not-both-filled="field1" form="form1"/>
    </p>
    <p ng-show="form1.$invalid">not valid</p>
    <p ng-show="!form1.$invalid">valid</p>
</form>

JS:

JS:

angular.module('myApp', []).directive('notBothFilled', function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
            var validateNotBothFilled = function(value) {
                var form = scope[attrs.form];
                var theOther = form[attrs.notBothFilled];
                var isNotValid = (value && value !== '' && theOther.$modelValue && theOther.$modelValue !== '');
                ctrl.$setValidity('field', !isNotValid);//set validity of the current element
                theOther.$setValidity('field', !isNotValid);//set validity of the other element.
                return value;
            };

            ctrl.$parsers.unshift(validateNotBothFilled);

        }
    };
});

DEMO

DEMO