myApp.directive('uiConstraints',[function(){ function applyConstraints(element,newVal,oldVal){ //remove old constraints if(oldVal !== undefined && oldVal !== null){ for (var i = 0; i < oldVal.length; i++) { element.removeAttr(oldVal[i].key); } } //apply new constraints if(newVal !== undefined && newVal !== null){ for (var i = 0; i < newVal.length; i++) { var constraint = newVal[i]; element.attr(constraint.key,constraint.value); } } } function link(scope,element,attrs){ scope.$watch(attrs.uiConstraints,function(newVal,oldVal){ applyConstraints(element,oldVal); }); } return { restrict : 'A',link : link }; }]);
所需的行为是如此在official angularjs plunker上工作.但是,似乎在指令填充输入字段的约束之前创建FormController,并且更新这些约束不会更新FormController中的相应值.
any1是否知道我是否可以强制FormController获取指令所产生约束的更改?如果是这样,怎么样?我不知道从哪里开始……谢谢.
– 编辑 –
我无法找到工作人员(向他人展示我的最新变化)所以这里是我所拥有的jsfiddle:latest
更详细地描述了这个问题:
>转到描述的jsfiddle
>如果从文本框中删除初始值,它将变为红色(无效),但是控制器不会选择它并仍将显示:
myform.$valid = true
myform.myfield.$valid = true
– 编辑 –
赏金描述无法识别Stack Overflow格式(如新行等2个空格),所以这里的形式更易读:
Since this is still unsolved and interesting question I decided to start a bounty.
The requirements are:
– works on ancient AngularJS(1.0.3) and newer (if it can’t be done on 1.0.3 but someone did it on newer version of angular I will award bounty)
– initially a field has no constraints on it (is not required,max and min not set etc)
– at any time constraints for the field can change (it can become required,or a pattern for the value is set etc),as well as any existing constraints can be removed
– all constraints are stored in a controller in an object or array
– FormController picks up the changes,so that any $scope.FormName.$valid is being changed appropriately when constraints
on any fields in that form changeA good starting point is my 07003.
Thanks for your time and good luck!
解决方法
.directive('uiConstraints',["$compile",function($compile) { function applyConstraints(element,oldVal) { //apply new constraints if (newVal !== undefined && newVal !== null) { for (var i = 0; i < newVal.length; i++) { var constraint = newVal[i]; element.attr(constraint.key,constraint.value); } } } return { restrict: 'A',terminal: true,priority: 1000,require: "^form",link: function(scope,attrs,formController) { var templateElement; var prevIoUsTemplate; templateElement = element.clone(); //get the template element and store it templateElement.removeAttr("ui-constraints");// remove the directive so that the next compile does not run this directive again prevIoUsTemplate = element; scope.$watch(attrs.uiConstraints,oldVal) { var clonedTemplate = templateElement.clone(); applyConstraints(clonedTemplate,newVal); clonedTemplate.insertBefore(prevIoUsTemplate); var control = formController[prevIoUsTemplate.attr("name")]; if (control){ formController.$removeControl(control); } if (prevIoUsTemplate) { prevIoUsTemplate.remove(); } $compile(clonedTemplate)(scope); prevIoUsTemplate = clonedTemplate; }); } }; }]);
这里的想法是设置terminal:true和priority:1000让我们的指令首先编译并跳过同一元素上的所有其他指令以获取模板元素.如果您需要了解更多信息,请查看我的答案:Add directives from directive in AngularJS.
获取模板元素后,我删除了ui-constraints指令,以避免一次又一次地编译该指令,这会在每次切换约束时向摘要周期添加$watch.
每当约束发生变化时,我都会使用此模板元素构建一个包含所有约束的新元素,而不使用ui-constraints指令并对其进行编译.然后我从表单控制器中删除DOM及其控制器中的前一个元素,以避免泄漏和由表单控制器中存在的前一个元素的控制器引起的问题.