Angular 2 - 如何使用下拉列表的值生成表单?

时间:2018-01-25 10:37:41

标签: angular

我需要一些建议才能在我的angular2应用程序中实现一个表单。

我有一个情境对象,其中包含三个重要的东西:id,name,type 在表单中,我创建了一个带有情境名称的下拉列表(我使用服务来获取列表并使用ngFor指令来显示) 根据所选情况的类型,我使用自己的formControls构建一个formGroup(我在下拉列表中使用onChange函数) 我使用类型在模板中显示新输入(许多情况可以具有相同的类型)。 我的模板中有这个代码有问题,当我选择一个值时,所选的值不再出现...

下面是我的代码片段,用以理解我在说什么:

模板

<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();
}

您对显示器问题有什么想法吗? 也许我使用了错误的做法......

我现在已经坚持了一段时间,欢迎你的所有建议,谢谢。

3 个答案:

答案 0 :(得分:2)

问题:

  • 您在构建表单时重置name表单控件

  • 您正在使用对象作为select的值。即使您没有遇到上述问题,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

答案 1 :(得分:0)

我认为问题是因为它在表单内部。每次构建新表单时,您都会生成一个新选择,但这没有任何价值。尝试移动选择

答案 2 :(得分:0)

您正在将反应驱动的表单构建与模板驱动的表单构建混合在一起。

指令“[(ngModel)]”用于模板驱动的表单。

您需要将模板更改为:

  <select class="form-control" formControlName="name">
    <option [value]="situation.type" *ngFor="let situation of situationsArray">
      {{situation.name}}
    </option>  
  </select>

这会在下拉列表中显示situation.name,当选择一个时,formControl的值将设置为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 - 我建议阅读评论及其中的各种答案。