web-dev-qa-db-ja.com

Angularマテリアルコンポーネントを使用したフォーム変更イベント

入力およびマテリアルコンポーネント(_mat-select_または_mat-checkbox_など)を含むフォームがあります。

ユーザーが変更を加えるたびに、それらをDBに保持したいと思います。だから私は<form (change)="save()">のようなことをしました。

これはネイティブ入力に対して問題なく機能しますが、ユーザーがマテリアルコンポーネントの値を変更しても起動しません。

フォームを更新する必要があるときに追加するのを簡単に忘れてしまう可能性があるため、すべてのコンポーネントで<mat-select (selectionChange)="save()">を使用するようなソリューションは避けたいと思います。

編集

これはテンプレート駆動型のフォームです。私のテンプレートは次のとおりです。

_<form (change)="save()">
    <!-- Will trigger save -->
    <mat-form-field class="col">
        <input matInput placeholder="Name" name="name" [(ngModel)]="item.name">
    </mat-form-field>

    <!-- Will NOT trigger save -->
    <mat-form-field class="col">
        <mat-select placeholder="Category" name="category [(ngModel)]="item.category.id">
            <mat-option *ngFor="let category of categories" [value]="category.id">{{category.name}}</mat-option>
        </mat-select>
    </mat-form-field>

    <!-- ... -->
</form>
_

コンポーネントコードには特に何もありません。モデル変数(_item: Item;_)だけです。

3
Sébastien

変更トラッカー を使用すると、この問題を解決できます。

次の例を確認してください。

import { Component , KeyValueChanges, KeyValueDiffer, KeyValueDiffers, DoCheck, OnInit } from '@angular/core';

@Component({
  selector: 'input-overview-example',
  styleUrls: ['input-overview-example.css'],
  templateUrl: 'input-overview-example.html',
})
export class InputOverviewExample implements OnInit, DoCheck {
  categories = [
    { id: 'id-1', name: 'Category 1' },
    { id: 'id-2', name: 'Category 2' },
    { id: 'id-3', name: 'Category 3' },
  ] as ExampleCategory[];
  item = new ExampleItem('Item One', this.categories[0].id);
  itemDiffer: KeyValueDiffer<string, any>;

  constructor(private readonly differs: KeyValueDiffers) { }

  ngOnInit() {
    this.itemDiffer = this.differs.find(this.item).create();
  }

  ngDoCheck(): void {
    const changes = this.itemDiffer.diff(this.item);
    if (changes) {
      //TODO: Save data here
      console.log("changed to: " + JSON.stringify(this.item));
    }
  }
}

export class ExampleItem {
  constructor(
    public name: string,
    public categoryId: string) {
  }
}

export class ExampleCategory {
  constructor(
    public id: string,
    public name: string) {
  }
}

そしてコンポーネントHTML:

<form>
    <mat-form-field class="col">
        <input matInput placeholder="Name" name="name" [(ngModel)]="item.name">
    </mat-form-field>

    <mat-form-field class="col">
        <mat-select placeholder="Category" name="category" [(ngModel)]="item.categoryId" required>
            <mat-option *ngFor="let category of categories" [value]="category.id">{{category.name}}</mat-option>
        </mat-select>
    </mat-form-field>
</form>

これがお役に立てば幸いです。

2
dbvega

<form (change)="save()" [formGroup]="form">をラップすることはできます

次に、他のマットコンポーネントの周りに<mat-form-field>を使用します。フォームグループでリッスンする必要があります。コンポーネントは、formControlName = ""で識別子を取得できます

1
Nikolai Kiefer