【问题标题】:Angular 2 - how to generate forms with the values of a dropdown list?Angular 2 - 如何使用下拉列表的值生成表单?
【发布时间】: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();
}

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

我现在被困了一段时间,欢迎您的所有建议,谢谢。

【问题讨论】:

    标签: angular


    【解决方案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】:

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

        【讨论】:

          猜你喜欢
          • 2017-06-07
          • 2016-11-16
          • 1970-01-01
          • 2017-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多