我想选择一个带有从其他输入中读取的选项的选择,并且当输入更改时,我的选择也将更改。
所有选择和输入均为反应形式。 问题是当我更改输入的值时,仅当我将选项值设置为表单控件时,选择选项才会更新。如果将options的值设置为form control的值,则不会更新它们。
示例代码在这里:https://stackblitz.com/edit/angular-5zfocw
模板:
<form [formGroup]="form">
<div formArrayName="opts" *ngFor="let opt of form.get('opts').controls; let i = index">
<div [formGroupName]="i">
{{i}}:
<input type="text" formControlName="name">
</div>
</div>
</form>
<form [formGroup]="form">
<label> Selection:</label>
<select formControlName="selection">
<option *ngFor="let opt of form.get('opts').controls; let i=index" [value]="opt.value.name">
{{opt.value.name}}
</option>
</select>
</form>
<hr>
<pre>
selection: {{ form.get('selection').value | json}}
</pre>
组件:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public form: FormGroup
constructor(private fb: FormBuilder){
this.form = this.fb.group({
opts: this.fb.array([
this.fb.group({name: ['N0']}),
this.fb.group({name: ['N1']}),
this.fb.group({name: ['N2']})
]),
selection: [{value: {}}]
})
}
}
如果我将HTML模板中的第13行更改为:
<option *ngFor="let opt of form.get('opts').controls; let i=index" [value]="opt">
然后,该选项和输入将完美同步。但是,我无法获得选择的值。
如果将行更改回[value]="opt.value.name"
,然后选择N2,然后更改N2输入,我的选择将丢失并且该值不会更新。
我想要1.从下拉列表中选择N2。 2.将N2更改为输入中的其他内容,例如N22。 3.选择应更新为N22。 N22值应显示在页面底部。
我该怎么办?
答案 0 :(得分:3)
您需要检查何时更改数组。为此,请订阅this.form.get('opts')。valueChanges。使用成对获取旧值并更改选择的值。
在代码中,创建表单后
this.form.get('opts').valueChanges.pipe(
startWith(this.form.value.opts),
pairwise())
.subscribe(([old,value])=>{
const index=old?old.findIndex(x=>x.name==this.form.get('selection').value):-1
if (index>=0)
this.form.get('selection').setValue(value[index].name,{emit:false})
})
更新,如果我们可以删除/添加一些值,则数组也会发生变化。因此,如果删除元素,则需要考虑到。因此,代码变为:
this.form.get('opts').valueChanges.pipe(
startWith(this.form.value.opts),
pairwise())
.subscribe(([old, value]) => {
if (old.length > value.length) { //if we remove some value
//we search if "selection" is in the new value
const index = value? value.findIndex(x => x.name == this.form.get('selection').value) : -1;
if (index == -1) //if not, simple equal to ""
this.form.get('selection').setValue("", { emit: false })
}
else { //Only change the value if we are not removing
const index = old ? old.findIndex(x => x.name == this.form.get('selection').value) : -1
if (index >= 0)
this.form.get('selection').setValue(value[index].name, { emit: false })
}
})
答案 1 :(得分:0)
经过多次尝试和错误后,我想出了另一种解决方案(或解决方法?),只需将其发布在此处以供参考。
我们可以直接使用FormControl作为值,而不是使用字符串值作为选项的值,并且将其连接到输入,因此它们都将同步在一起。
https://stackblitz.com/edit/angular-musy61
HTML文件中的此部分,请参见[ngValue]="opt"
<select formControlName="selection">
<option *ngFor="let opt of opts.controls; let i=index" [ngValue]="opt">
{{opt.value.name}}
</option>
</select>
尝试从选择项中选择N2
,然后在输入中编辑N2
。查看所有内容如何一起更新。
问题在于,当检索出值时,它是一个表单控件。因此,该值很麻烦selection.value.value.name