[英]Detach then append AngularJS form change validity status
你可以在这个jsFiddle中测试它: HERE (更好的是看到新的jsFiddle,请参阅本文的EDIT部分)
我认为AngularJS中存在一个错误,或者至少没有预期的结果。 如果我分离一个表单然后重新附加它,它的类ng-invalid
切换到ng-valid
重新附加到DOM。 因此,即使数据无效,也可以启用表单的提交按钮。 当然,我期待有效状态没有改变。
我认为这是一个有角度的错误,但也许是一个jquery。 如果表单有效,我可以使用jquery检查append,然后强制表单类,但它似乎不能作为有效表单获取然后无效状态。 这是非常奇怪的,因为我不知道任何其他解决方法,如果没有使用类型的数据来保存状态表单,然后再分离它。
所以任何人都已经遇到过这个问题? 是否有任何方法(如果可能使用AngularJS指令)摆脱这个错误?
PS:我需要在单页Web应用程序中分离表单(和任何其他元素),以尽可能保持DOM的清洁。
编辑
我做了一个新的jsFiddle,它解释了我的问题,在内部网站导航上分离了内容: http : //jsfiddle.net/EWVwa/
UPDATE
我来到这个临时解决方案(感谢CaioToOn)
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive('customValidation', function() {
return {
require: ['ngModel', '^?form'],
link: function(scope, element, attr, ctrls) {
console.log(ctrls);
var ngModelCtrl = ctrls[0],
formCtrl = ctrls[1];
ngModelCtrl.$parsers.push(function(viewValue) {
if (viewValue === 'test') {
ngModelCtrl.$setValidity('name', true);
formCtrl.$setValidity('name', true);
return viewValue;
} else {
ngModelCtrl.$setValidity('name', false);
formCtrl.$setValidity('name', false);
return undefined;
}
});
// custom event
element.bind('$append', function() {
formCtrl && formCtrl.$addControl(ngModelCtrl);
/*** TEST for to keep form's validation status ***/
formCtrl.$setValidity('name', ngModelCtrl.$valid);
//ngModelCtrl.$setValidity('name', ngModelCtrl.$valid);
console.log(formCtrl.$valid);
});
//binding on element, not scope.
element.bind('$destroy', function() {
console.log("gone haven");
});
}
};
});
这需要更多关于多输入验证的测试。 当所有测试都完成时,我肯定会更新答案。
问题发生的原因是当从DOM中删除元素时, input
指令将自己从表单控件中删除。 由于它不会再次链接您的ngModel
和表单控制器,因此表单不再考虑您的输入。
你基本上有
两个
选择:
更改元素可见性意味着您将在DOMTree中拥有不必要的DOM元素。 这并不是很糟糕,因为你总是保留对$ compile元素的引用,所以它还将参与$digest
循环和“DOM”修改。
( 经过一段时间的考虑,新的解决方案略好于此,因此不要暴露
重新
链接功能 )
暴露重新链接功能
非常奇怪(虽然功能齐全),这不是最可靠的解决方案。 实现它的一种方法是需要表单控制器( require: ['ngModel', '^?form']
)并将重新链接函数绑定到元素的数据:
element.data('relink', function(){
formCtrl && formCtrl.$addControl(ngModelCtrl);
});
当您再次将元素添加到屏幕时,您将不得不调用所有控件重新链接功能:
$('.controls').data('relink')();
在这里查看示例。
它不太可靠,但可能适用于您的情况。
触发自定义事件与前一个事件几乎相同,但是您将在应该重新链接自己的所有元素上调度自定义事件。 这种方式更有条理,但仍然不太可靠,因为表单和其他链接也可能已被破坏(同样,应该会使您的情况更糟)。 基本上听你的指令上的自定义事件:
element.bind('$append', function(){
formCtrl && formCtrl.$addControl(ngModelCtrl);
});
更改为表单后,只需在所有控件上触发自定义事件:
$('.control').triggerHandler('$append');
这个更好的原因是指令仍然决定何时重新链接组件,并且事件是一种“通用”。 这是一个工作的plunker 。
作为最后的努力,您可以覆盖jQuery.fn.append
并递归地触发所有元素子jQuery.fn.append
的自定义事件(这是Angular在删除元素时所做的 )。 这是最有条理的,但它会影响所有append
调用的性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.