在发布之前,Angular2的各个版本已多次询问此问题的风味。但是,我还没有找到任何可以产生所需行为的东西(我想避免的解决方法):Select Object Problems
我的表单选择通过[(ngModel)]与对象进行双向绑定,然后选择'选项'通过* ngFor生成类似对象的列表(全部由id区分)。在我的研究中,已多次提到Angular2使用JavaScript对象等效(通过实例),因此绑定模型中没有相同实例的对象将与列表不匹配。因此,它不会被显示为"选择"项目 - 打破" 2-way"数据绑定。
但是,我想为这些实例定义匹配的方法。已经尝试了一些似乎在互联网上浮现的解决方案,但我要么丢失了一小块,要么实施不正确。
我想避免的选项:
理想情况下(这似乎已经在几个有解决方案的地方进行了讨论 - 在我的情况下解决方案不足),有可能为ngModel定义一个相等的标准来代替对象实例相等。
即。下面的最新尝试,其中h.id == a.id定义了属性" selected"。我不明白为什么这个"选择"属性不会被渲染 - 是否被ngModel以某种方式阻止?设置选中=' true' HTML中的手动似乎已修复,但使用[attr.selected]或任何其他构建ng-reflect-selected =' true'属性似乎没有成功。
<div *ngFor='let a of activePerson.hobbyList ; let i=index; trackBy:a?.id'>
<label for='personHobbies'>Hobby:</label>
<select id='personHobbies' class='form-control'
name='personHobbies' [(ngModel)]='activePerson.hobbyList[i]' #name='ngModel'>
<option *ngFor='let h of hobbyListSelect; trackBy:h?.id'
[ngValue]='h'
[attr.selected]='h.id == a.id ? true : null'
>
{{h.name}}
</option>
</select>
</div>
我尝试过的一些事情:
我已成功实现了如下所示的呈现HTML:
<select ...>
<option selected='true'>Selected</option>
<option selected='false'>Not Selected</option>
<!-- and variants, excluding with selected=null-->
</select>
但是当对象实例不同时,仍然没有选择的值。我还试图找出HTML或CSS中的哪个元素在用户选择值时记录所选值(ngModel如何处理,以及可能有哪些其他选项用于处理)。
非常感谢任何帮助。目标是获得&#34;变更&#34;按钮来更改基础模型并相应地更新选择框 - 我已将我的尝试集中在&#34; hobbyList。&#34;我试过Firefox和Chrome。谢谢!
答案 0 :(得分:12)
Per @Klinki
目前在角度2中没有简单的解决方案,但在角度4中 自从beta 6使用以来,这已经得到了解决
compareWith
- 见https://github.com/angular/angular/pull/13349
说明拟议案例(see plunk)的用法:
<div *ngFor='let a of activePerson.hobbyList ; let i=index;'>
<label for='personHobbies'>Hobby:</label>
<select id='personHobbies' class='form-control'
name='personHobbies' [(ngModel)]='activePerson.hobbyList[i]'
[compareWith]='customCompareHobby'>
<option *ngFor='let h of hobbyListSelect;' [ngValue]='h'>{{h.name}}</option>
</select>
</div>
...
customCompareHobby(o1: Hobby, o2: Hobby) {
return o1.id == o2.id;
}
答案 1 :(得分:4)
目前在角度2中没有简单的解决方案,但在角度4中,这已经从beta 6开始解决了 - 请参阅https://github.com/angular/angular/pull/13349
答案 2 :(得分:0)
如果从某个地方传递了想要制作所选对象的对象,只需在hobbyListSelect
数组中搜索匹配项,并将找到的项目分配给activePerson.hobbyList[i]
答案 3 :(得分:0)
以这种方式使用ngModel绑定没有直接的方法。 但是,由于您不希望单独注册事件处理程序,我们可能需要更改对象的分配方式。 此外,您无需为select标记分配id,因为它不符合目的。 对于上面提到的用例,我修改了它以查看双向绑定。
使用model查找组件的构造函数,并包含printVal()以测试更改。模板不包括ngValue和ngModel,它仍然可以按预期工作。
constructor() {
this.activePerson = {id: 'a1',
hobbyList : [
{
id: 'h4'
},
{
id : 'h2'
}
]
}
this.hobbyListSelect = [
{
id: 'h1'
},
{
id : 'h2'
},
{
id: 'h3'
},
{
id : 'h4'
}
];
}
printVal($event,i) {
console.log(JSON.stringify(this.activePerson.hobbyList))
}
&#13;
<div *ngFor='let a of activePerson.hobbyList ; let i=index; trackBy:a?.id'>
<label for='personHobbies'>Hobby:</label>
<select name='personHobbies'
(change)=" activePerson.hobbyList[i] = hobbyListSelect[$event.target.selectedIndex];
printVal($event,i)">
<option *ngFor='let h of hobbyListSelect; trackBy:h?.id'
[selected]='(h.id == a.id) ? "selected" : null'
>
{{h.id}}
</option>
</select>
</div>
&#13;
答案 4 :(得分:0)
[compareWith]解决了这个问题。只需在compareObj方法中更改要比较的对象的正确属性即可。
<select [compareWith]="compareObj" [(ngModel)]="selectedObjects">
<option *ngFor="let object of objects" [ngValue]="object">
{{object.name}}
</option>
</select>
compareObj(o1: Object, o2: Object) {
return o1.id === o2.id;
}