我有一个Angular 6,Reactive Forms项目,它连接到ASP.NET Web Api 2 / MS SQL Server 2017后端。我正在连接前端,遇到了一个我还没有遇到的情况,找不到如何完成的例子:
Nested FormGroups,其对象由select
元素表示。到目前为止,我没有错误,它似乎在加载时下拉列表中选择了正确的项目。但是,在选择时,仅更新一个字段而不是整个对象。
我想我需要使用formGroupName="company"
告诉registerOnChange()
要查找哪个控件,然后使用某种形式的formControlName="..."
,但我不明白如何使用select
或option
元素来实现我正在寻找的东西。我需要一个选择来更新整个对象,包括id和name属性。
Click here to view the StackBlitz editor/demo
...
<form class="form-horizontal" novalidate (ngSubmit)="save()" [formGroup]="siteForm">
<fieldset>
...
<div class="form-group" formGroupName="company">
<label class="col-md-2 control-label" for="companyId">Company</label>
<div class="col-md-8">
<select id="companyId" class="form-control" formControlName="company">
<option *ngFor="let company of companies" [ngValue]="company.name">
{{ company.name }}
</option>
</select>
</div>
</div>
...
</fieldset>
</form>
siteForm: FormGroup;
// TODO: refactor to use http Company Service instead
companies: Company[] = [
{ id: 1, name: 'Company 1'},
{ id: 2, name: 'Company 2'},
{ id: 3, name: 'Company 3'}
];
site: Site;
constructor(private fb: FormBuilder,
private siteService: SiteService) { }
ngOnInit(): void {
this.siteForm = this.fb.group({
...
company: this.fb.group({
id: null,
name: ''
}),
...
});
}
getSite(id: number): void {
this.siteService.getSite(id)
.subscribe(site => this.onSiteRetrieved(site));
}
save(): void {
if (this.siteForm.dirty && this.siteForm.valid) {
// copy form values over the site object values
const s = Object.assign({}, this.site, this.siteForm.value);
// simulate call to save service
console.log('Saved: ' + JSON.stringify(s));
}
}
onSiteRetrieved(site: Site): void {
// clear all the state flags (dirty, touched, etc.)
if (this.siteForm) {
this.siteForm.reset();
}
this.site = site;
// update the data on the form
this.siteForm.setValue({
...
company: {
id: this.site.company.id,
name: this.site.company.name
},
...
});
}
... more
答案 0 :(得分:1)
因为有很多代码需要连接,我相信这就是你需要的,
<select formControlName="id">
<option *ngFor="let company of companies" [ngValue]="company.id">{{country.name}}</option>
</select>
上述解决方案是正确的,但您需要对stackblitz进行一些更改,我已经为您修好了,请查看this
this.siteForm.patchValue
中的setValue
请注意公司名称不要更新,如果您需要更改公司名称,您必须订阅更改活动并更改表单或更改site
对象和补丁表格
答案 1 :(得分:0)
我已经按照Angular的SetControlValueAccessor模型驱动示例解决了这个问题,它使用对象标识来选择选项。
<强> Click here to see StackBlitz demo 强>
我从包装div中删除formGroupName="company"
,在整个对象formControlName="company"
上使用select
,然后在[ngValue]="company"
上使用option
也是整个对象。
见下文:
<div class="form-group">
<label class="col-xs-2 control-label" for="companyId">Company</label>
<div class="col-xs-8">
<select id="companyId"
class="form-control"
formControlName="company"
[compareWith]="compareCompanies">
<option *ngFor="let company of companies" [ngValue]="company">
{{ company.name }}
</option>
</select>
</div>
</div>
我需要在课堂上做出的唯一改变是:
company: this.fb.group({ id:
null, name: ''})
的FormGroup分配,并将其替换为company: null
。 compareWith
功能。 需要,因为默认比较使用对象标识,不同的对象具有不同的标识。您可以使用自己的实现覆盖此方法以确定唯一性。 见下文:
ngOnInit(): void {
this.siteForm = this.fb.group({
name: ['', Validators.required],
company: null
});
...
}
compareCompanies(c1: Company, c2: Company): boolean {
return c1 && c2 ? c1.id === c2.id : c1 === c2;
}