在Angular中,我如何进入可能深入的子范围来改变有效性等问题?

时间:2014-09-21 19:04:23

标签: angularjs angularjs-directive angularjs-scope

我有一个简单的表单,如下所示:

<form name="myForm">
  <input name="field" ng-model="item.field"></input>
  <button ng-click="save()">Save</button>
</form>

理论上,我应该能够根据表单和字段更改控制器中字段的有效性等内容,如下所示:

$scope.save = function(item) {
  item.$save();
  $scope.myForm.field.$setValidity("some-error",false);
};

问题在于各个级别的指令会妨碍并且可能会设置多个子范围。因此,虽然item.field被正确渲染和链接,但我从控制器做任何事情的能力都非常有限,例如:如果我将我的部分包装在一个隐藏它的花哨的“加载”指令中并显示“加载”直到完成。

<loading>
  <form name="myForm">
    <input name="field" ng-model="item.field"></input>
    <button ng-click="save()">Save</button>
  </form>
</loading>

现在,我想要直接设置有效性的控制器不再可以访问$scope.myForm。事实是,在可能的指令下,从不可以安全地依赖$scope.myForm的访问权;只有一个指令可以!

@Beyers建议将表单作为save()调用的一部分传递为<button ng-click="save(myForm)">Save</button>,这肯定有效,但会变得很麻烦。

是否有一种真正的Angular方式可以干净利落地完成这项工作?我应该直接在控制器内重置为$pristine,还是还有其他事情要做?

更新:

我开始怀疑这是否是正确的方法。我的控制器应该像表单上的$setValidity一样吗?它不应该从视图中获取输入并在此基础上修改业务对象(item),以及与服务进行交互吗?角度如何知道重置ng-dirtyng-invalid进行自己的验证?

2 个答案:

答案 0 :(得分:0)

上次我这样做时,我只是抓住了Id的表单字段并且工作正常。 使用ID,你“Angularize”它,然后你可以访问它的模型等...

像这样:

//you will need to add an id to your field.
var myInput = angular.element(document.querySelector('#myInput'));
var ngModelCtrl = myInput.controller('ngModel');

ngModelCtrl.$setValidity("some-error",false);

有角度的文档说你应该只在必要的时候这样做,他们更喜欢你使用ngModel.$validators pipline。不幸的是,我不确定如何自己使用它,所以无法帮助你。

答案 1 :(得分:0)

  

问题在于各个级别的指令会妨碍并且可能会设置多个子范围。

您正在遇到标准if you don't have a dot in your model, you're doing it wrong问题。这不仅适用于ng-model,也适用于表单名称。

解决方案是确保控制器中有一个表单,例如forms

$scope.forms = {};

在模板中使用forms.<formName>

<form name="forms.myForm">
  ...
</form>

然后在控制器代码中访问表单,使用$scope.forms.<formName>

$scope.forms.myForm.field.$setValidity("some-error" ,false);

您的更新问题:

  

我的控制器是否应该像表单上的$ setValidity那样执行此操作

我会根据具体情况来解决这个问题,以便KISS。有效性通常是与服务交互的结果,并且可以与业务对象/规则相关。我想说控制器中的一些代码与验证相互作用是可以的,但是如果你的控制器有很长的责任,那么尝试将一些逻辑移入可能是一个好主意。需要ngModel的元素的自定义指令。然后,如果需要,这些可以通过控制器设置的属性接受参数/功能。