I have a form that contains inputs and material components (like mat-select
or mat-checkbox
).
Each time a modification is made by the user, I want to persist them to the DB. So I did something like <form (change)="save()">
.
This is working flawlessly for the native inputs, but it doesn't fire when the user changes a material component value.
I'd rather avoid solutions like using <mat-select (selectionChange)="save()">
on every component, as I could easily forget to add it when I'll have to update my form.
Edit
This is a template driven form. My template is as follow:
<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>
The component code has nothing particular, only the model variable (item: Item;
).
Matinput is an Angular directive that primarily allows input and text area elements to work with a form field. With this, you can display placeholders perfectly, add custom error messages, a clear button, specify the maximum length of the text or add prefixes and suffixes for a seamless user experience.
MatFormFieldControl. An interface which allows a control to work inside of a MatFormField .
html - matSuffix makes mat-icon not horizontally centered in mat-icon-button - Stack Overflow.
Whenever your input is changed, angular accesses the variable the string is set in. One way to do something when the variable changes would be to use a get ter and set ter. Everything else remains the same. And you just have to use ngModel on text.
this solution works for Angular 11.2.1 and Material 11.2.1
You need to capture the changes with valueChanges observable
this.editForm.valueChanges
.subscribe(value=> {
if (this.editForm.dirty) {
//do something
}
});
Notes to observe:
again this works with reactive forms, I just noticed your question uses Template-driven but worth noting just in case someone is looking at solution for reactive forms.
Using a change tracker you can solve this problem.
Check the following example:
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) {
}
}
And the component 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>
I hope this helps!
you can still wrap a
<form (change)="save()" [formGroup]="form">
around it
then use a <mat-form-field>
around your other mat components. it should listen on the formgroup. The components can get an identifyer with formControlName=""
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With