实现一个指令以从验证中排除隐藏的输入元素($ addControl issue)

时间:2014-02-05 10:47:07

标签: forms angularjs validation

我正在创建一个指令,要求从验证中排除隐藏的输入元素:http://plnkr.co/edit/Vnwvq2AT7JpgTnoQwGh9?p=preview

app.directive('shownValidation', function() {
    return {
      require: '^form',
      restrict: 'A',
      link: function(scope, element, attrs,form) {
        var control;

        scope.$watch(attrs.ngShow,function(value){
          if (!control){
            control = form[element.attr("name")];
          }
          if (value == true){
            form.$addControl(control);
          }else{
             form.$removeControl(control);
          }
        });
      }
    };
  });

这里的想法是如果元素被隐藏,我将从表单中删除控件,以便它不会影响其他输入有效性。当我调用form.$removeControl(control);时,它可以正常工作,您可以在演示中通过删除名字并单击按钮来隐藏字段来测试它。

但是当我再次点击该按钮时,即使名字无效(空),表单有效性仍然是正确的

我还尝试添加form.$setValidity(form.$valid && control.$valid) =>有效性状态按预期更新,但当我输入第一个名称时,有效性仍为假。

我的问题是如何解决这个问题?感谢您的回复。

更新

感谢@ Michael的回答。这是工作解决方案:

app.directive('shownValidation', function() {
  return {
    require: '^form',
    restrict: 'A',
    link: function(scope, element, attrs, form) {
      var control;

      scope.$watch(attrs.ngShow, function(value) {
        if (!control) {
          control = form[element.attr("name")];
        }
        if (value == true) {
          form.$addControl(control);
     //Add a forEach to manually update form validity.Thanks to @Michael's answer
          angular.forEach(control.$error, function(validity, validationToken) {
            form.$setValidity(validationToken, !validity, control);
          });
        } else {
          form.$removeControl(control);
        }
      });
    }
  };
});

Working plunk

2 个答案:

答案 0 :(得分:12)

如果删除控件,则会更新有效性(来自源):

  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, function(queue, validationToken) {
      form.$setValidity(validationToken, true, control);
    });

    arrayRemove(controls, control);
  };

如果添加控件角度没有更新有效性(来自源):

  form.$addControl = function(control) {
    // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
    // and not added to the scope.  Now we throw an error.
    assertNotHasOwnProperty(control.$name, 'input');
    controls.push(control);

    if (control.$name) {
      form[control.$name] = control;
    }
  };

因此我们必须手动执行此操作。我猜是这样的:

if (value == true){
    form.$addControl(control); 
    angular.forEach(control.$error, function(validity, validationToken) {
       form.$setValidity(validationToken, !validity, control);
    });
   }else{
    form.$removeControl(control);
   }
}

答案 1 :(得分:4)

您似乎正在使用ng-show隐藏元素,因此不会随表单一起提交输入。

在这种情况下,我们可以在视图中使用ng-if指令,以便动态删除元素。 这将删除元素,它也是有效的。