I have a component with several checkboxes, drop-downs, and a save button. Here is a simplified example component template:
<aside class="container">
<div class="row">
<input
type="checkbox"
id="all-users"
[(ngModel)]="showAllUsers"
(ngModelChange)="onChange($event)"
/>
<label for="all-users">Show all users</label>
</div>
<div class="row">
<ng-select
[(ngModel)]="selectedUser"
[clearable]="false"
appendTo="body"
(change)="onChange($event)"
>
<ng-option *ngFor="let user of activeUsers" [value]="user">{{ user }}</ng-option>
</ng-select>
</div>
<div class="row">
<button type="button" class="btn btn-primary" [disabled]="!dirty" (click)="onSave()">
Save Changes
</button>
</div>
</aside>
I want to enable the Save Changes button only when the user made a change, either by unchecking the check-box or changing a selection in drop-down box.
Right now I have an event handler registered at each and every control in the component (the onChange function in the example above), and use a dirty flag to disable or enable the Save Changes button.
Here is the component.ts for the above template:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.css']
})
export class FilterComponent implements OnInit {
dirty: boolean;
showAllUsers: boolean;
selectedUser: string;
activeUsers: string[];
ngOnInit() {
this.dirty = false;
this.showAllUsers = true;
this.activeUsers = ['Thanos', 'Thor', 'Starlord'];
this.selectedUser = 'Thor';
}
onChange(event) {
console.log('Event is ' + event);
this.dirty = true;
}
onSave() {
console.log('Gonna save changes...');
this.dirty = false;
}
}
Registering the event handler to every control does not seem intuitive to me.
Is this the correct approach to figure out a change made by user or does angular provide a different way to achieve this?
I would highly recommand using both FormGroup and FormControl to achieve this behavior.
Both exposes the dirty property, a read-only boolean.
The
dirtyproperty is set totruewhen the user changes the value of theFormControlfrom the UI. In the case of theFormGroup, the dirty property is set totrueas long as at least 1 of theFormControlin that group is dirty.As a side note, the property
pristineis the opposite property. So you can use one or the other if it simplifies the condition.[disabled]="myFormGroup.pristine"might be easier to read than[disabled]="!myFormGroup.dirty".