表单验证 - 组中许多必需的一个

ali*_*c83 17 angularjs

在我正在研究的项目中,目前我有三个文本框,我需要验证至少有一个文本框已经填充.

我一直在阅读Angular指令的自定义验证,我知道您可以使用以下命令设置指令链接函数中输入的有效性:

ctrl.$parsers.unshift(function(viewValue) {
  // validation logic here
});
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我不需要设置单个输入的有效性.如果不符合标准,我需要使整个表单无效.我只是想知道如何处理这个问题?

我想也许我应该创建一个放在封闭表单上的指令,然后使表单无效?

我想我只是在寻找一些关于我应该怎么做的指导,因为我有点不清楚从哪里开始 - 我正在阅读自定义验证的所有材料似乎都是为了验证特定的输入而不是表格上的一系列条件.

我希望我已经清楚了!谢谢..

Jul*_*ien 42

您可以使用ng-required强制用户通过检查字符串的长度属性来填充至少一个字段.

您可以执行以下操作,例如:

<form name="myForm">
            <input type="text" ng-model="fields.one" name="firstField" ng-required="!(fields.one.length || fields.two.length || fields.three.length)" />
            <br/>
            <input type="text" name="secondField" ng-required="!(fields.one.length || fields.two.length || fields.three.length)" ng-model="fields.two" />
            <br/>
            <input type="text" ng-model="fields.three" name="thirdField" ng-required="!(fields.one.length || fields.two.length || fields.three.length)" />
            <br/>
            <button type="submit" ng-disabled="!myForm.$valid">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此工作小提琴示例.

通过阅读此问题,您可以获得有关所需 vs ng-required的更多详细信息


gka*_*pak 23

有几种方法,最佳选择取决于您的确切要求.

这是我发现的一种通用的,足够灵活的方法.
通过"通用"我的意思是它不只能用于文本字段,但也适用于其他种类的投入,如支票盒.
它是"灵活的",因为它允许任意数量的控制组,这样每组的至少一个控件必须是非空的.此外,没有"空间"约束 - 每个组的控件可以在DOM内的任何位置(如果需要,很容易将它们限制在单个内部form).

该方法基于定义自定义指令(requiredAny),类似于ngRequired,但考虑到同一组中的其他控件.一旦定义,该指令可以像这样使用:

<form name="myForm" ...>
  <input name="inp1" ng-model="..." required-any="group1" />
  <input name="inp2" ng-model="..." required-any="group1" />
  <input name="inp3" ng-model="..." required-any="group1" />

  <input name="inp4" ng-model="..." required-any="group2" />
  <input name="inp5" ng-model="..." required-any="group2" />
</form>
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,[inp1,inp2,inp3]中的至少一个必须是非空的,因为它们属于group1.
同样适用于[inp4,inp5],属于group2.


该指令如下所示:

app.directive('requiredAny', function () {
  // Map for holding the state of each group.
  var groups = {};

  // Helper function: Determines if at least one control
  //                  in the group is non-empty.
  function determineIfRequired(groupName) {
    var group = groups[groupName];
    if (!group) return false;

    var keys = Object.keys(group);
    return keys.every(function (key) {
      return (key === 'isRequired') || !group[key];
    });
  }

  return {
    restrict: 'A',
    require: '?ngModel',
    scope: {},   // An isolate scope is used for easier/cleaner
                 // $watching and cleanup (on destruction).
    link: function postLink(scope, elem, attrs, modelCtrl) {
      // If there is no `ngModel` or no groupName has been specified,
      // then there is nothing we can do.
      if (!modelCtrl || !attrs.requiredAny) return;

      // Get a hold on the group's state object.
      // (If it doesn't exist, initialize it first.)
      var groupName = attrs.requiredAny;
      if (groups[groupName] === undefined) {
        groups[groupName] = {isRequired: true};
      }

      var group = scope.group = groups[groupName];

      // Clean up when the element is removed.
      scope.$on('$destroy', function () {
        delete(group[scope.$id]);
        if (Object.keys(group).length <= 1) {
          delete(groups[groupName]);
        }
      });

      // Update the validity state for the 'required' error-key
      // based on the group's status.
      function updateValidity() {
        if (group.isRequired) {
          modelCtrl.$setValidity('required', false);
        } else {
          modelCtrl.$setValidity('required', true);
        }
      }

      // Update the group's state and this control's validity.
      function validate(value) {
        group[scope.$id] = !modelCtrl.$isEmpty(value);
        group.isRequired = determineIfRequired(groupName);
        updateValidity();
        return group.isRequired ? undefined : value;
      }

      // Make sure re-validation takes place whenever:
      //   either the control's value changes
      //   or the group's `isRequired` property changes
      modelCtrl.$formatters.push(validate);
      modelCtrl.$parsers.unshift(validate);
      scope.$watch('group.isRequired', updateValidity);
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

这可能不会那么短,但一旦包含在模块中,就很容易集成到表单中.


另请参阅此(不是那么)简短演示.


Ali*_*avi 9

现在为时已晚,但可能会节省一些时间:

如果只有两个字段,并且想要使其中一个字段需要

<input type="text" 
      ng-model="fields.one" 
      ng-required="!fields.two" />
<br/>
<input type="text" 
      ng-model="fields.two"
      ng-required="!fields.one"  />
Run Code Online (Sandbox Code Playgroud)

如果你有三个问题那么

<input type="text" 
      ng-model="fields.one" 
      ng-required="!(fields.two || fields.three)" />
<br/>
<input type="text" 
      ng-model="fields.two"
      ng-required="!(fields.one || fields.three)"  />
<br/>
<input type="text" 
      ng-model="fields.three" 
      ng-required="!(fields.one|| fields.two)" />
Run Code Online (Sandbox Code Playgroud)

如果不止于此,我建议在示波器上编写一个函数并观察它.

请参阅工作示例


Mil*_*lad 0

您可以为每个属性添加必需的属性,最后,您可以依赖每个/所有/或仅其中一个的验证

        <form name="form" novalidate ng-submit="submit()">
        // novalidate is form disabling your browser's own validation mechanism

          <input type="text" required ng-model="texts.text1"> 
          <input type="text" required ng-model="texts.text2"> 
          <input type="text" required ng-model="texts.text3"> 
          // you can do validation in variety of ways , but one of them is to disable your submit button until one of the textboxes are filled correctly like this : 

          <button type="submit" ng-disabled="form.text1.$invalid && form.text2.$invalid && form.text3.$invalid"></button>      

        </form>
Run Code Online (Sandbox Code Playgroud)

这样,如果只有其中一个被填充,按钮将被启用

我不知道你将如何表明该表单无效,但我认为禁用提交按钮是一般方法