Reputation: 95
I have a question on how two-way binding work in Angular Material checkbox.
This is HTML template from app.component.html
:
<div>
<div *ngFor="let data of testData">
<mat-checkbox [(ngModel)]="data.isActive" (change)="handleData(data)">{{data.isActive}}</mat-checkbox>
</div>
</div>
And this is the component (app.component.ts
):
import { Component } from '@angular/core';
import { OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
testData: TestData[];
ngOnInit() {
this.testData = [];
this.testData.push({
label: 'testData1',
isActive: false
});
this.testData.push({
label: 'testData2',
isActive: false
});
}
handleData(data: TestData) {
console.log(data.isActive);
data.isActive = false;
}
}
export class TestData {
label: string;
isActive: boolean;
}
All the checkboxes are unchecked by default. When I click a checkbox for the first time, the data
parameter in the handleData
handler receives true
in data.isActive
. I set this to false
afterwards. The corresponding labels are never changed (they are always false
). But I also expect for a checkbox never be checked as well. But it does is checked. Why this happens?
UPDATED I've just added the 'Results' section that contains checkboxes that reflect the ones above:
<div>
<div *ngFor="let data of testData">
<mat-checkbox [(ngModel)]="data.isActive" (change)="handleData(data)">{{data.isActive}}</mat-checkbox>
</div>
</div>
<h2 class="example-h2">Result</h2>
<div>
<div *ngFor="let data of testData">
<mat-checkbox [(ngModel)]="data.isActive" (change)="handleData(data)">{{data.isActive}}</mat-checkbox>
</div>
</div>
Unlike their neighbours above they are never checked.
Upvotes: 1
Views: 7636
Reputation: 73731
The value may be reset too quickly, when Angular has not completed the change detection cycle triggered by the click. It works if we reset the value asynchronously with setTimeout
(see this stackblitz):
handleData(data: TestData) {
console.log(data.isActive);
setTimeout(() => {
data.isActive = false;
});
}
or if we call ChangeDetectofRef.detectChanges()
before resetting the value (see this stackblitz):
handleData(data: TestData) {
console.log(data.isActive);
this.changeDetectorRef.detectChanges();
data.isActive = false;
}
Upvotes: 4