【问题标题】:Angular 5 + Angular Material Select + Reactive Forms == No initial options displayedAngular 5 + Angular Material Select + Reactive Forms == 不显示初始选项
【发布时间】:2018-10-14 05:06:06
【问题描述】:

正如标题所说,我有一个反应形式,其中包含多个 <mat-select>。在初始表单加载时,即使form.value 显示初始选项也不会显示。

相关组件.ts:

export class DesJobInfoEditComponent implements OnInit {

...

currentJobData: IJob;
jobTypes: IJobType[];

...

constructor(private fb: FormBuilder) {

    ...

        // Construct forms
        this.createForm();

        this.initializeForm();

}

createForm() {
    this.editJobInfoForm = this.fb.group({
        ...
        JobType: '', // mat-select
        ...
    });
}

initializeForm() {
    this.rebuildForm();
}

rebuildForm() {
    this.editJobInfoForm.reset({
        ...
        JobType: this.jobTypes[this.currentJobData.JobType].DisplayDesc,
        ...
    });
}

}

相关的html:

<mat-form-field fxFlex>
      <mat-label>Job Type</mat-label>
       <mat-select formControlName="JobType" placeholder="Job Type">
              <mat-option *ngFor="let jobType of jobTypes" value="jobType.value">
                     {{ jobType.DisplayDesc }}
               </mat-option>
        </mat-select>
  </mat-form-field>

当表单加载时,选择不显示最初选择的选项,但是,显然它们设置正确:

Form value { ... "JobType": "0 - Standard", ... } 

表单上显示的只是占位符。

这似乎不应该这么难。

我做错了什么?

编辑:

this.jobTypes 在加载模块时加载,它是一个存在于我的数据服务中的 BehaviorSubject。因此,我在该组件的构造函数中订阅了它:

this.data.jobTypes.subscribe(jobTypes =&gt; { this.jobTypes = jobTypes });

【问题讨论】:

  • 也许你需要管道异步? let jobType of jobTypes | async
  • 你是如何加载jobTypes的?我没有看到填充 this.jobTypes 的代码
  • @Stanton 我已经更新了我的问题。
  • 您对此有任何更新吗?我遇到了完全相同的问题...当我更改为简单的 HTML 时,选择一切正常...

标签: angular angular-material angular-reactive-forms


【解决方案1】:

一些事情

  1. [formControlName] 必须[formGroup]结合使用。如果不想使用[formControlName] + [formGroup],可以改用[formControl]

  2. 在 Angular 中,将属性指定为 value[value] 是有区别的。当一个属性括在括号 [] 中时,它被解释为 javascript / 角度模板脚本(我认为与 {{}} 相同)。当括在括号中时,会被解释为字符串(即value="jobType.value" === [value]="'jobType.value'"[value]="jobType.value" === value="{{jobType.value}}"(其实我觉得有细微差别在[value]="jobType.value"value="{{jobType.value}}" 之间,但w/e))。因此,当您编写&lt;mat-option *ngFor="let jobType of jobTypes" value="jobType.value"&gt; 时,每个mat-option 的值都是"jobType.value",我想这不是您想要的。所以需要把代码改成&lt;mat-option *ngFor="let jobType of jobTypes" [value]="jobType.value"&gt;

例如

<mat-form-field [formGroup]='editJobInfoForm' fxFlex>
  <mat-label>Job Type</mat-label>
  <mat-select formControlName="JobType" placeholder="Job Type">
    <mat-option *ngFor="let jobType of jobTypes" [value]="jobType.value">
      {{ jobType.DisplayDesc }}
    </mat-option>
  </mat-select>
</mat-form-field>

与您的问题有点无关,为什么createForm()initializeForm() 方法都有?为什么不简单

constructor(private fb: FormBuilder) {

    ...

        // Construct forms
        this.createForm();    
}

createForm() {
    this.editJobInfoForm = this.fb.group({
        ...
        JobType: this.jobTypes[this.currentJobData.JobType].DisplayDesc,
        ...
    });
}

【讨论】:

  • 解释得很好——我的赞美!
【解决方案2】:

按原样使用与函数进行比较...

Step1:如图所示放置[compareWith]标签

<mat-form-field>
  <mat-select placeholder="Pick item..." formControlName="selectedItem" 
    [compareWith]="compareFn">
    <mat-option *ngFor="let item of items">
        {{item.name}}
    </mat-option>
  </mat-select>
</mat-form-field>
<button (click)="changeValue()">Change value</button>

第 2 步:声明变量 compareFn 和函数 compareByValue 如下所示,无需更改

compareFn: ((f1: any, f2: any) => boolean) | null = this.compareByValue;

compareByValue(f1: any, f2: any) { 
  return f1 && f2 && f1.name === f2.name; 
}

【讨论】:

    【解决方案3】:

    您好,我知道它为时已晚,但我知道一个更简单的解决方案。 您的 UI (html) 组件描述正确

    在您的打字稿中,您将对象与不会产生任何验证的字符串进行比较。 所以总是将对象与 null 进行比较(在验证中)

    只需在createForm() { this.editJobInfoForm = this.fb.group({ ... JobType: '', // mat-select ... }); }

    更改JobType: '' 替换为JobType:[null]

    【讨论】:

      【解决方案4】:

      Angalural Material compareWith: (o1: any, o2: any) => boolean from (API reference for Angular Material select)

      组件.ts

       export class ParentOneComponent implements OnInit {
        materialFormSample: FormGroup;
        constructor() { }
      
        ngOnInit() {
          this.configureMaterialFormSample();
        }
        name: string = 'Emilius Patrin Mfuruki';
        toppingList: string[] = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato'];
        selectedToppingList = ['Extra cheese', 'Tomato', 'Onion'];
      
        compareWithFunc = (a: any, b: any) => a == b;
      
        configureMaterialFormSample() {
          this.materialFormSample = new FormGroup({
            name: new FormControl(this.name),
            toppings: new FormControl(this.selectedToppingList)
          })
        }
        onSubmitForm() {
          if (this.materialFormSample.valid) {
            console.log('submitting Form Content Valid', this.materialFormSample.value);
          }
        }
      }
      

      component.html

      <form [formGroup]="materialFormSample" (ngSubmit)="onSubmitForm()" autocomplete="off">
            <mat-form-field class="w-100">
              <input matInput placeholder="Name" formControlName="name">
            </mat-form-field>
            <mat-form-field class="w-100">
              <mat-label>Toppings</mat-label>
              <mat-select formControlName="toppings" multiple [compareWith]="compareWithFunc">
                <mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping}}</mat-option>
              </mat-select>
            </mat-form-field>
            <div class="clearfix">
              <button type="submit" mat-raised-button color="primary" class="float-right">Submit Form</button>
            </div>
          </form>
      

      【讨论】:

        猜你喜欢
        • 2021-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-06
        • 2017-06-17
        • 1970-01-01
        相关资源
        最近更新 更多