具有材料成分的角形更改事件

时间:2018-11-20 15:56:14

标签: angular forms angular-material onchange

我有一个包含输入材料成分(例如mat-selectmat-checkbox)的表单。

每次用户进行修改时,我都希望将其持久保存到数据库中。所以我做了类似<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 个答案:

答案 0 :(得分:3)

此解决方案适用于 Angular 11.2.1 和 Material 11.2.1

你需要用 valueChanges observable 捕捉变化

this.editForm.valueChanges
 .subscribe(value=> {
       if (this.editForm.dirty) {
              //do something
              }
           });

注意事项:

  1. 通常你不需要放置过滤器 if(this.editForm.dirty) {...} ,因为正常的行为是这个观察者只有在它被改变(脏)时才应该启动,但是由于材料组件 mat-xxx,这个观察者在字段的值改变后被踢了几次,所以为了避免对事件进行多次不必要的执行,你必须通过这个条件过滤 observable if (this.editForm.dirty) {。 ..} 它只会在更改后执行。

这同样适用于响应式表单,我刚刚注意到您的问题使用了模板驱动,但值得注意的是,以防有人正在寻找响应式表单的解决方案。

答案 1 :(得分:1)

您仍然可以包装一个       <form (change)="save()" [formGroup]="form">周围

然后在其他垫子组件周围使用<mat-form-field>。它应该在formgroup上侦听。组件可以使用formControlName =“”

获得标识。

答案 2 :(得分:0)

使用change tracker可以解决此问题。

检查以下示例:

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>

我希望这会有所帮助!