2

I'm trying to implement select all checkbox on angular material. When user click on specifc checkbox (item), master checkbox should show Indeterminate and turn to checked if all checkboxes are selected. Currently I'm having some weird behaviour. Can anyone let me know where I made mistake? Here is stackblitz. Here is my sample code:

app.html

<fieldset class="demo-fieldset">
  <div>
    <mat-checkbox aria-label="Select All" [checked]="isChecked(selected3, itemsObject)" [indeterminate]="isIndeterminate(selected3, itemsObject)" (click)="toggleAll(selected3, itemsObject)">
      Select All list of user (Array of objects) {{isChecked(selected3, itemsObject)}}
    </mat-checkbox>
  </div>
  <div class="demo-select-all-checkboxes" *ngFor="let item of itemsObject">
    <mat-checkbox [checked]="exists(item, selected3)" (click)="toggle(item, selected3)">
      {{ item.val }}
    </mat-checkbox>
    {{exists(item, selected3)}}

  </div>
</fieldset>

app.ts

import {
  Component
} from '@angular/core';

@Component({
  selector: 'app',
  templateUrl: 'app.html',
  styleUrls: ['app.css'],
})
export class CheckboxConfigurableExample {
  itemsObject = [{
    id: 1,
    val: 'john'
  }, {
    id: 2,
    val: 'jane'
  }];
  selected3 = [];

  toggle(item, list) {
    var idx = list.indexOf(item);
    if (idx > -1) {
      list.splice(idx, 1);
    } else {
      list.push(item);
    }
  }

  exists(item, list) {
    return list.indexOf(item) > -1;
  };

  isIndeterminate(x, t) {
    return (x.length !== 0 && x.length !== t.length);
  };

  isChecked(x, t) {
    return x.length === t.length;
  };

  toggleAll(x, t) {
    var l1 = x.length,
      l2 = t.length;
    if (l1 === l2) {
      x.splice(0, l1);
    } else if (l1 === 0 || l1 > 0) {
      //First we need to empty array, because we are using push to fill in array
      x.splice(0, l2);
      t.forEach(y => x.push(y));
    }
  };
}

Here is my stackblitz

5 Answers 5

9

Try this code:

Component:

import {Component} from '@angular/core';
import {

  MatCheckboxChange
} from '@angular/material';

/**
 * @title Configurable checkbox
 */
@Component({
  selector: 'checkbox-configurable-example',
  templateUrl: 'checkbox-configurable-example.html',
  styleUrls: ['checkbox-configurable-example.css'],
})
export class CheckboxConfigurableExample {
  itemsObject = [{
    id: 1,
    val: 'john'
  }, {
    id: 2,
    val: 'jane'
  }];
  selected3 = [];

  toggle(item,event: MatCheckboxChange) {
     if (event.checked) {
      this.selected3.push(item);
    } else {
      const index = this.selected3.indexOf(item);
      if (index >= 0) {
        this.selected3.splice(index, 1);
      }
    }
   console.log(item + "<>", event.checked);
  }

  exists(item) {
    return this.selected3.indexOf(item) > -1;
  };

  isIndeterminate() {
    return (this.selected3.length > 0 && !this.isChecked());
  };

  isChecked() {
    return this.selected3.length === this.itemsObject.length;
  };



  toggleAll(event: MatCheckboxChange) { 

    if ( event.checked ) {

       this.itemsObject.forEach(row => {
          // console.log('checked row', row);
          this.selected3.push(row)
          });

        // console.log('checked here');
    } else {
      // console.log('checked false');
       this.selected3.length = 0 ;
    }
}
}

Template:

<fieldset class="demo-fieldset">
  <div>
     <mat-checkbox aria-label="Select All" [checked]="isChecked()" [indeterminate]="isIndeterminate()" (change)="$event ? toggleAll($event) : null">
      Select All list of user (Array of objects) {{isChecked(selected3)}}
    </mat-checkbox>
  </div>
  <div class="demo-select-all-checkboxes" *ngFor="let item of itemsObject">
    <mat-checkbox (click)="$event.stopPropagation()"
                    (change)="$event ? toggle(item, $event) : null"
                    [checked]="exists(item)">
      {{ item.val }}
    </mat-checkbox>
    {{exists(item)}}

  </div>
</fieldset>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you guys. Working like charm
1

A different strategy might be to bind to values on an object and component, instead of calling methods. This way, you may be able to manage the state more effectively in your component.

For example, you could introduce the following in your object model:

public itemsObject = [{
  id: 1,
  val: 'john',
  isChecked: false
}, {
  id: 2,
  val: 'jane',
  isChecked: false
}];

You can then bind this to the checkboxes using:

[checked]="item.isChecked"

Binding the the "change" event will also let you know when things are changed, and you can then act accordingly:

<mat-checkbox [checked]="item.isChecked" (change)="itemChanged(item,$event)">

I created a Stackblitz which shows a working example:-

https://stackblitz.com/edit/angular-uuw7qh-ninwen

Comments

0

In your checkbox-configurable-example.html you use:

[checked] = "isChecked(selected3, itemsObject)"

I simply changed this to:

value="isChecked(selected3, itemsObject)"

And it looks as you expect? I suspect some more tweaking is needed for the overall project, but this might get you in the direction?

1 Comment

I see this creates other issues.
0

On your Html, Add something like below:

<table class="table">
              <thead>
                <tr>
                  <th>
                    <mat-checkbox (change)="onChangeSelectAll($event)">Select/Deselect All</mat-checkbox>
                  </th>

                </tr>
              </thead>
              <tbody>
                <tr *ngFor="let item of offers">
                  <td>
                    <mat-checkbox [checked]="item.selected" (change)="selection($event, i, item)" name="chkInvoice"></mat-checkbox>
                  </td>                      
                </tr>
              </tbody>
            </table>

ON your typescript file,

onChangeSelectAll(event) {
    if (event.checked) {
        this.offers.forEach(obj => {
            obj.selected = true;
        });
    }
    else {
        this.offers.forEach(obj => {
            obj.selected = false;
        });
    }
}

Comments

0

Another version without using selected3 array

.html file

<fieldset class="demo-fieldset">
    <div>
        <mat-checkbox aria-label="Select All" [checked]="isChecked()" [indeterminate]="isIndeterminate()"
            (change)="toggleAll($event)">
            Select All list of user (Array of objects) {{isChecked()}}
        </mat-checkbox>
    </div>
    <div class="demo-select-all-checkboxes" *ngFor="let item of itemsObject">
        <mat-checkbox [checked]="item.selected" (change)="toggle(item)">
            {{ item.val }}
        </mat-checkbox>
        {{exists(item)}}
    </div>
</fieldset>

.ts file

Added 'selected' key to itemsObject for binding checkbox value. Define itemsObject and allCheckboxSelected.

 itemsObject = [
    {
      id: 1,
      val: 'john',
      selected: false
    },
    {
      id: 2,
      val: 'jane',
      selected: false
    }
  ];
  allCheckboxSelected;


toggleAll(event: MatCheckboxChange) {
    if (event.checked) {
      this.itemsObject.forEach(element => {
        element.selected = true;
      });
    } else {
      this.itemsObject.forEach(element => {
        element.selected = false;
      });
    }
  }

  isChecked() {
    this.allCheckboxSelected =
      this.itemsObject.length != 0 && this.itemsObject.every(el => el.selected);
    return this.allCheckboxSelected;
  }

  isIndeterminate() {
    if (this.itemsObject.length === 0) {
      return false;
    }
    return (
      this.itemsObject.some(el => el.selected) && !this.allCheckboxSelected
    );
  }

  toggle(checkbox) {
    let index = this.itemsObject.findIndex(el => el.id === checkbox.id);
    this.itemsObject[index].selected = !this.itemsObject[index].selected;
  }

  exists(item) {
    let index = this.itemsObject.findIndex(el => el.id === item.id);
    return this.itemsObject[index].selected;
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.