[英]Angular directives with ng-if seem to loose model
I am fairly new to Angular and trying to make a directive that will construct a form input, usually a text-input, but sometimes a select box based on whether or not the input is associated with an array of options. 我对Angular很新,并试图制作一个指令,它将构造一个表单输入,通常是一个文本输入,但有时候是一个基于输入是否与一个选项数组相关联的选择框。 Simplifying down, my code looks roughly like this: 简化,我的代码大致如下:
html HTML
<init ng-init = "ops = [
{value:'hello',label:'Hello All'},
{value:'bye',label:'Good-bye everyone'}]"></init>
<init ng-init = "fType =
{id:'greeting',label:'Greeting',type:'enum', 'options':ops}">
</init>
<simpleselect field="fType" ng-Model="foomodel"></simpleselect>
{{foomodel}}
Directive 指示
.directive('simpleselect',function(){
return {
restrict: 'E',
replace:true,
template:[
'<div><select ',
'ng-if ="type=\'select\'"',
'name="{{field.id}}"',
'ng-model="ngModel" ',
'ng-options="option.value as option.label for option in field.options">',
'</select>{{ngModel}}</div>',
].join(),
scope:{
field:'=',
ngModel:'='
},
link:function(scope, elem, attrs, ctrl){
scope.type = 'select';
}
}
});
This almost works. 这几乎可行。 If I remove the ng-if on the select box, my select box and my model stay in sync just fine. 如果我在选择框中删除ng-if,我的选择框和我的模型保持同步就好了。 But what I want is to be able to choose which control within the directive. 但我想要的是能够选择指令中的哪个控件。 Is this a misuse of ng-if and is there another path? 这是对ng-if的误用吗?还有其他途径吗?
Can use template:function(element,attrs)
if using angular version >=1.1.4 如果使用angular version> = 1.1.4 template:function(element,attrs)
可以使用template:function(element,attrs)
template:function(element,attrs){
var template='<div>';
var type= attrs.fieldType;
if( type=='select'){
template+='<select ng-options=......>';
}
if( type=='text' ){
template +='<input ......./>';
}
template +='</div>';
return template;
}
Modify your template as follows: 修改模板如下:
template: [
'<div ng-if="field.type==\'select\'">', // <-- move ng-if here
'<select name="{{field.id}}"',
'ng-model="ngModel" ',
'ng-options="option.value as option.label for option in field.options">',
'</select>',
'{{ngModel}}',
'</div>'
].join(''),
Also note there are couple of errors: 另请注意,有几个错误:
1). 1)。 ng-if
should have ==
instead of =
and field.type
instead of just type
ng-if
应该有==
而不是=
和field.type
而不仅仅是type
2). 2)。 .join('')
instead of .join()
.join('')
而不是.join()
As a couple of folks suggested, I could have used ng-show, but I didn't want to pollute my DOM with all the input types I was not using. 正如一些人建议的那样,我本可以使用ng-show,但我不想用我没有使用的所有输入类型来污染我的DOM。 I also could have set my directive with a list of individual properties instead of passing in a 'field' object and then watching them in my template function to determine the particulars of my input, like charlietfl's solution. 我也可以用一个单独的属性列表设置我的指令,而不是传入一个'field'对象,然后在我的模板函数中观察它们以确定我输入的细节,比如charlietfl的解决方案。
Instead, since I want to determine which input type control to use based on a number of attributes in the model itself, I have chosen to resolve a good portion of the rendering of my control in the link method of my directive, using the $compile service. 相反,由于我想根据模型本身的许多属性确定要使用哪个输入类型控件,我选择使用$ compile在我的指令的链接方法中解析我的控件的很大一部分渲染。服务。 Then I can both make macro layout decisions based on the model I pass into scope and still resolve the particulars of each input using angular style template syntax. 然后我可以根据我传入范围的模型做出宏布局决策,并且仍然使用角度样式模板语法解决每个输入的细节。
For a simple selectbox, this would have been overkill and either of the two other answers here would have been better, but because I want my directive to determine if a control should be a text input, textarea, selectbox, radio buttons, or checkboxes depending only on the requirements of the model I need to be able to read the model first and then compile with it. 对于一个简单的选择框,这本来是矫枉过正的,这里的其他两个答案中的任何一个都会更好,但因为我希望我的指令确定控件是否应该是文本输入,textarea,selectbox,单选按钮或取决于复选框只有模型的要求我才能首先读取模型,然后用它进行编译。
Doing rendering in the link method feels a bit wrong, so I don't mean to be saying I have a great solution, but if it helps anyone, that's great. 在链接方法中进行渲染感觉有点不对,所以我并不是说我有一个很好的解决方案,但如果它对任何人都有帮助,那就太好了。 If others with more experience with Angular than me find that offensive, I would also love to be straightened out. 如果对Angular有更多经验的人比我发现那些令人反感的话,我也会喜欢被理顺。 :^) :^)
Here is an example of my more complicated checkbox option within the directive: 这是我在指令中更复杂的复选框选项的示例:
link:function(scope, elem, attrs, ctrl){
...some logic to examine the model to determine which input type to use...
if(scope.type === 'checkbox'){
if(typeof scope.ngModel === 'string') scope.ngModel = scope.ngModel.split(/[ ,]+/);
tmp = [
'<div class="option chk tall" ng-repeat="option in field.options">',
'<label><input ng-model="ngModel" ng-value="option.value" ng-checked="ngModel.indexOf(option.value) > -1" name="{{field.id}}" type="checkbox" />{{option.label}}</label>',
'<div class="description">{{option.description}}</div>',
'</div>{{ngModel}}'].join('');
elem.on('change',function(e){
if(e.target.checked && scope.ngModel.indexOf(e.target.value) < 0) scope.ngModel.push(e.target.value);
if(!e.target.checked)
scope.ngModel.splice(scope.ngModel.indexOf(e.target.value),1);
});
}
elem.find('div').html(tmp);
$compile(elem.contents())(scope);
}
I am not at all in love with the on-click stuff to keep my model and UI in sync, but for now, I am going to live with it. 我一点也不喜欢点击的东西,以保持我的模型和UI同步,但是现在,我将继续使用它。
I had a similar problem and you can actually access the parent model via $parent.boundattribute . 我遇到了类似的问题,您实际上可以通过$ parent.boundattribute访问父模型。
As described somewhere in the comments, ng-if adds a subscope and thus the model does not update backwards. 如评论中某处所述,ng-if添加了一个子范围,因此模型不会向后更新。
In my case ng-show would not work, I had to really remove the part of the DOM and this solved the problem. 在我的情况下,ng-show不起作用,我必须真正删除DOM的一部分,这解决了问题。
<select ng-if="type='select'"
name="{{field.id}}"
ng-model="$parent.ngModel"
ng-options="option.value as option.label for option in field.options">
</select>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.