web-dev-qa-db-ja.com

Angular 5 + Angular Material Select + Reactive Forms ==初期オプションは表示されません

タイトルにあるように、複数の_<mat-select>_が含まれるリアクティブフォームがあります。初期フォームのロード時に、_form.value_が表示されていても初期オプションは表示されません。

関連するcomponent.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 => { this.jobTypes = jobTypes });

6
OCDDev

いくつかのこと

  1. [formControlName]must[formGroup]と組み合わせて使用​​します。 [formControlName] + [formGroup]を使用したくない場合は、代わりに[formControl]を使用できます。

  2. 角度では、属性をvalue[value]として指定することには違いがあります。属性がブラケット[]で囲まれている場合、次のように解釈されます javascript / angular template script({{}}と同じ、私は思う)。それがnot括弧で囲まれている場合、それは文字列として解釈される(すなわちvalue="jobType.value" === [value]="'jobType.value'"[value]="jobType.value" === value="{{jobType.value}}"(実際、[value]="jobType.value"value="{{jobType.value}}"には微妙な違いがあると思いますが、w/e))ですから、<mat-option *ngFor="let jobType of jobTypes" value="jobType.value">を書くとき、mat-optionの値は"jobType.value"になります。したがって、コードを<mat-option *ngFor="let jobType of jobTypes" [value]="jobType.value">に変更する必要があります

例えば.

<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,
        ...
    });
}
6
John

関数との比較をそのまま使用...

手順1:[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; 
}
1
thakkar sagar

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

component.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>
1
Emilius Mfuruki

こんにちは、私はそれが遅すぎることを知っていますが、より簡単な解決策を知っています。 U I(html)コンポーネントが正しく記述されている

typeScriptでは、検証を行わない文字列とオブジェクトを比較しています。したがって、常にオブジェクトをnullと比較します(検証中)

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

変化する JobType: '' と置換する JobType:[null]

0
Sohail Anwar