Angular 2 - 如何使用下拉列表的值生成表单?
Posted
技术标签:
【中文标题】Angular 2 - 如何使用下拉列表的值生成表单?【英文标题】:Angular 2 - how to generate forms with the values of a dropdown list? 【发布时间】:2018-07-04 13:56:55 【问题描述】:我需要一些建议来在我的 angular2 应用程序中实现表单。
我有一个情境对象,它包含三个重要的东西:id、name、type 在一个表单中,我创建了一个带有情况名称的下拉列表(我使用服务来获取列表并使用 ngFor 指令来显示) 根据所选情况的类型,我用那些自己的formControls构建了一个formGroup(我在下拉列表中使用了onChange函数) 我使用类型来显示模板中的新输入(许多情况可以具有相同的类型)。 我的模板中有此代码的问题,当我选择一个值时,所选值不再出现...
下面是我的代码的 sn-p,以了解我在说什么:
模板:
<form [formGroup]="myForm" (ngSubmit)="saveForm()" novalidate>
<select class="form-control" [(ngModel)]="selectedSituation" (change)="onChangeSituation()" formControlName="name">
<option [ngValue]="situation" *ngFor="let situation of situationsArray">situation.name</option>
</select>
<div *ngIf="selectedSituation?.type == 1">
<!-- some fields -->
</div>
<div *ngIf="selectedSituation?.type == 2">
<!-- other fields -->
</div>
</form>
组件:
situationsArray: string[];
selectedSituation: any;
type: any;
constructor(
private _fb: FormBuilder
)
createDefaultForm()
this.myForm = this._fb.group(
name: ['', Validators.required]
// inputs not concerning by dropdown list
);
createType1Form()
this.myForm = this._fb.group(
name: ['', Validators.required]
// inputs for type = 1
);
createType2Form()
this.myForm = this._fb.group(
name: ['', Validators.required]
// inputs for type = 2
);
ngOnInit()
this.createDefaultForm(); // a formGroup for the inputs who aren't concerned by the dropdwon list
this.getListSituations(); // a service to get the situations list
onChangeSituation(): void
console.log(this.selectedSituation);
if(this.selectedSituation.type == 1)
this.createJobForm();
else
if(this.selectedSituation.type == 2)
this.createPeForm();
else
if(this.selectedSituation.type == 3)
this.createPeaForm();
else
this.createDefaultForm();
您对显示问题有任何想法吗? 也许我使用了错误的做法......
我现在被困了一段时间,欢迎您的所有建议,谢谢。
【问题讨论】:
【参考方案1】:问题:
您在构建表单时正在重置 name
表单控件
您正在使用一个对象作为选择的值。即使您没有上述问题,Angular 也无法在不相互引用的情况下匹配对象值。
其次,就像其他答案中提到的那样,不要混合模板驱动和反应式表单,它们真的不适合。
我要做的是更改选择,例如您正在寻找的type
,然后为条件字段创建一个子表单组。这样,您只需切换子组,而无需重建所有常见(如果有的话)字段。所以像....(缩短的代码)
createDefaultForm()
this.myForm = this._fb.group(
name: ['', Validators.required],
// other inputs
subGroup: this._fb.group()
);
您选择切换子组的选项:
<select class="form-control" (change)="createSubForm()" formControlName="name">
<option [ngValue]="situation.type" *ngFor="let situation of situationsArray">
situation.name
</option>
然后是方法createSubGroup
:
createSubForm()
if (this.myForm.controls.name.value === 1)
this.myForm.setControl('subGroup', this.createType1Form())
else
this.myForm.setControl('subGroup', this.createType2Form())
createType1Form()
return this._fb.group(
name1: ['type1', Validators.required]
// inputs for type = 1
);
createType2Form()
return this._fb.group(
name2: ['type2', Validators.required]
// inputs for type = 2
);
展示此内容的 StackBlitz:DEMO
【讨论】:
【参考方案2】:您将反应驱动的表单构建与模板驱动的表单构建混合在一起。
指令“[(ngModel)]”用于模板驱动的表单。
你需要把模板改成这样:
<select class="form-control" formControlName="name">
<option [value]="situation.type" *ngFor="let situation of situationsArray">
situation.name
</option>
</select>
This will display situation.name's in the dropdown, and when one is selected, the value of the formControl
will be set to situation.type
.
在您的 ngOnInit 中:
this.myForm.controls['name'].valueChanges.subscribe(
value =>
console.log(value);
onChangeSituation(value);
);
然后将您的 onChangeSituation() 更改为:
onChangeSituation(newValue: number): void
switch(newValue)
case 1:
this.createJobForm();
break;
case 2:
this.createPeForm();
break;
case 3:
this.createPeaForm();
break;
default:
this.createDefaultForm();
break;
我假设 newValue 是一个数字。
编辑
但是,使用此解决方案,由于您创建了对表单控件的 valueChanges 的订阅,因此在销毁组件时需要取消订阅。有几种方法可以实现这一目标。问题描述为here。
推荐的解决方案描述为here。所以我会这样做:
在您的组件中添加一个新变量(主题):
destroy$: Subject<boolean> = new Subject<boolean>();
将订阅行修改为:
this.myForm.controls['name'].valueChanges.takeUntil(this.destroy$).subscribe(
添加 ngOnDestroy 方法:
ngOnDestroy()
this.destroy$.next(true);
// Now let's also unsubscribe from the subject itself:
this.destroy$.unsubscribe();
并修改你的组件类的签名来实现它:
export class MyComponent implements OnInit, OnDestroy
还有另一个解决方案 here 用于销毁订阅以及更多 here - 我建议阅读 cmets 和那里的各种答案。
【讨论】:
【参考方案3】:我认为问题在于表单内部。每次您构建一个新表单时,您都会生成一个新的选择,但这没有任何价值。尝试将选择移出
【讨论】:
以上是关于Angular 2 - 如何使用下拉列表的值生成表单?的主要内容,如果未能解决你的问题,请参考以下文章
Angular / RxJs对一个observable的多个订阅