Sergei Zhylinski
Sergei Zhylinski

Reputation: 95

Angular Material Checkbox Two-Way binding

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

Answers (1)

Martin Parenteau
Martin Parenteau

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

Related Questions