Add select all button to mat-select with mat-optgroup

Viewed 12198

I want to add the button "select all" and "deselect all" to a mat-select with groups division.

My code is available here: https://stackblitz.com/edit/angular5-selectall-with-groups?file=app/select-reset-example.html

This code is based on this working demo for a simple mat-select: https://stackblitz.com/edit/angular-material-select-multi-c6vtux?file=app%2Fapp.component.ts

In my code I need to loop over 4 arrays, so I started tested the "selectAll()" function for the first array. However, only the first checkbox is selected, even if the [ngModel] shows that the function takes all the values inside the array. I also need to make this function works for the other three arrays.

I hope someone can help me fix the problem. I can also change the code if there is a better way of doing what I am trying to achieve.

2 Answers

* I also Update your code please* https://stackblitz.com/edit/angular5-selectall-with-groups?file=app%2Fselect-reset-example.ts

HTML code is like this

 <form [formGroup]="roleForm " (ngSubmit)="onSubmit(roleForm .value)">

     <!-- Multi Select Mat Start -->
              <mat-form-field class="example-full-width">

                <mat-select placeholder="Select Privileges"  #selectedValues  class="filter-select" formControlName="privilegeMultiselect" 
                  multiple required >
                  <mat-option disabled="disabled" class="filter-option">
                    <button mat-raised-button class="mat-primary fill text-sm" (click)="selectAll(dropdownList)">
                      Select All 
                    </button>
                    <button  mat-raised-button class="mat-primary fill text-sm eta-margin-all" (click)="deselectAll()">
                      Deselect All
                    </button>
                  </mat-option>
                  <mat-option *ngFor="let privilege of dropdownList" [value]="privilege.id">{{privilege.itemName}}</mat-option>
                </mat-select>

              </mat-form-field>
              <!-- Multi select mat end -->

    </form>

Create form builder in ngoninit method

this.roleForm = this._formBuilder.group({
      privilegeMultiselect: []

    })

Those are your method to select your value

selectAll(list) {

    this.roleForm.get('privilegeMultiselect').patchValue(list)
  }
  deselectAll() {
    this.roleForm.get('privilegeMultiselect').patchValue([])
  }

You need to do the following:

  1. Remove an unncessary [(ngModel)] (you have two) and the [compareWith] from <mat-select>:
<mat-select placeholder="State2" multiple [(ngModel)]="modelGroup" #itemSelect="ngModel">...</mat-select>
  1. Instead of creating an array for each options group with regular expression you can create one single array called groups which will look like the following:
groups: any[] = [
    {
      name: 'ETHERNET',
      items: [
        {
          label: "640K",
          value: "BS640KB_ETHERNET",
          defaultValue: true
        },
        {
          label: "7MB",
          value: "BS7MB_ETHERNET",
          defaultValue: true
        },
        {
          label: "7MB NOQinQ",
          value: "BS7MB_ETHERNET_NOQinQ",
          defaultValue: true
        },
        {
          label: "20MB",
          value: "BS20MB_ETHERNET",
          defaultValue: true
        }
      ]
    },
    {
      name: 'ATM',
      items: [
        {
          label: "640K",
          value: "BS640K_ATM",
          defaultValue: true
        },
        {
          label: "7MB",
          value: "BS7M_ATM",
          defaultValue: true
        },
        {
          label: "20MB",
          value: "BS20M_ATM",
          defaultValue: true
        }
      ]
    },
    {
      name: 'ETH',
      items: [
        {
          label: "2MB",
          value: "BS2MB_SHDSL_ETH",
          defaultValue: true
        },
        {
          label: "4MB IMA",
          value: "BS4MB_SHDSL_ETH_IMA",
          defaultValue: true
        },
        {
          label: "6MB IMA",
          value: "BS6MB_SHDSL_ETH_IMA",
          defaultValue: true
        },
        {
          label: "8MB IMA",
          value: "BS8MB_SHDSL_ETH_IMA",
          defaultValue: true
        }
      ]
    },
    {
      name: 'SHDSL ATM',
      items: [
        {
          label: "2MB",
          value: "BS2MB_SHDSL",
          defaultValue: true
        },
        {
          label: "4MB B",
          value: "BS4MB_SHDSL_B",
          defaultValue: true
        },
        {
          label: "4MB IMA",
          value: "BS4MB_SHDSL_IMA",
          defaultValue: true
        },
        {
          label: "6MB IMA",
          value: "BS6MB_SHDSL_IMA",
          defaultValue: true
        },
        {
          label: "8MB IMA",
          value: "BS8MB_SHDSL_IMA",
          defaultValue: true
        }
      ]
    }
  ];

Furthermore you can remove all other arrays, regular expressions, your createCatArray() and equals() method.

  1. Now we can clean up the template. Go on and remove all existing <mat-optgroup>. Add now one single <mat-optgroup> which loops through your set up array groups and renders the corresponding items like the following:
<mat-optgroup *ngFor="let group of groups" [label]="group.name">
   <mat-option *ngFor="let item of group.items" [value]="item.value">
      {{item.label}}
   </mat-option>
</mat-optgroup>
  1. Remove now the parameter you have set up on the Select All button:
<button mat-button (click)="selectAll(itemSelect)">Seleziona Tutti</button>
  1. Now the last step is to change the selectAll() method. Within the method remove the parameter array and the existing for loop. Now we are going to loop through the set up groups array and add the value of each item in every group to a values array. This array will later be submitted to update the selected values. The method should look like the following:
selectAll(select: NgModel) {
  let values: any[] = [];

  for(let group of this.groups){
    for(let item of group.items){
      values.push(item.value);
    }
  }

  select.update.emit(values);
}

Basically we did the following:

  1. Created an array of groups which further contains the name of the group and the items which belong to the group.

  2. Loop through the array of groups to render the groups and their corresponding items in the html template.

  3. Added a select all method which loops through all groups items and add their value to an array which will be submitted later to update the selection.

Here is the functioning app:

https://stackblitz.com/edit/angular5-selectall-with-groups-knptuu

Related