0

I am trying to do select all for angular multiple selects, it works for one select but how can I make it work when you have more than 1 select? when i add select all for second input it selects all on first input

campaign.ts

  @ViewChild('mySel') skillSel: MatSelect;

  toggleAllSelection() {
    this.allSelected = !this.allSelected;

    if (this.allSelected) {
      this.skillSel.options.forEach( (item : MatOption) => item.select());
    } else {
      this.skillSel.options.forEach( (item : MatOption) => {item.deselect()});
    }
  }

campaign.html

  <mat-select #mySel multiple formControlName="Branch">
        <mat-option [value]="0" (click)="toggleAllSelection()">All items</mat-option>
        <mat-option *ngFor="let item of centers" [value]="item.centerCode">{{item.address}}</mat-option>
      </mat-select>

        <mat-select #mySel multiple formControlName="categoryDescriptions">
          <mat-option [value]="0" (click)="toggleAllSelection()">All items</mat-option>
          <mat-option *ngFor="let item of categories" [value]="item.description">{{item.description}}</mat-option>
        </mat-select>
zaqwsx
  • 53
  • 1
  • 9
  • For mat-select Select all and Deselect all try [this](https://stackoverflow.com/a/51580470/8213994) solution. – Aman Gojariya Feb 18 '21 at 08:45
  • hey, thanks for the answer i tried this too, but I have the same problem, how can i make this work when you have more than one select? – zaqwsx Feb 18 '21 at 09:10
  • https://stackoverflow.com/q/66163651/7821499 i have opened a question for that answer too – zaqwsx Feb 18 '21 at 09:11

1 Answers1

1

The problem is you have a single variable allSelected to control both of the mat-select boxes, and you have also given both mat-select boxes the same ID of mySel. This is why it selects all on the first mat-select when you use the select all option in the second one.

To fix this, give each mat-select a different ID e.g mySelBranch and mySelCategory:

<mat-form-field appearance="fill">
  <mat-label>Branch</mat-label>
  <mat-select #mySelBranch [formControl]="branch" multiple>
    <mat-option [value]="0" (click)="toggleAllSelection(mySel)">All items</mat-option>
    <mat-option *ngFor="let branch of branchList" [value]="branch">{{branch}}</mat-option>
  </mat-select>
</mat-form-field>

<mat-form-field appearance="fill">
  <mat-label>Category</mat-label>
  <mat-select #mySelCategory [formControl]="categoryDescriptions" multiple>
    <mat-option [value]="0" (click)="toggleAllSelection(mySel2)">All items</mat-option>
    <mat-option *ngFor="let category of categoryList" [value]="category">{{category}}</mat-option>
  </mat-select>
</mat-form-field>

And you'll notice I've also changed the call to toggleAllSelection - it now passes the mat-select in as a parameter.

The toggleAllSelection has been changed to:

toggleAllSelection(matSelect: MatSelect) {
    const isSelected: boolean = matSelect.options
      // The "Select All" item has the value 0, so find that one
      .filter((item: MatOption) => item.value === 0)
      // Get the value of the property 'selected' (this tells us whether "Select All" is selected or not)
      .map((item: MatOption) => item.selected)
      // Get the first element (there should only be 1 option with the value 0 in the select)
      [0];

    if (isSelected) {
      matSelect.options.forEach((item: MatOption) => item.select());
    } else {
      matSelect.options.forEach((item: MatOption) => item.deselect());
    } 
}

The first part of the function looks through the options of the mat-select passed in as a paramter, and finds the option with the value 0 (due to how you've defined your HTML, the "Select All" option always has the value 0). It then gets the value of the property name selected (this will be true is "Select All" is selected and false if it is deselected). As the result of this is an array, it then uses [0] to get the first item (there should only be a single item in the array at this point because of the filter function used:

const isSelected: boolean = matSelect.options
  .filter((item: MatOption) => item.value === 0)
  .map((item: MatOption) => item.selected)[0];

You no longer need the following variables in your TypeScript class:

@ViewChild("mySel") skillSel: MatSelect;
allSelected = false;

Please see this StackBlitz for a demo.

Ian A
  • 5,622
  • 2
  • 22
  • 31
  • thank u so much for your answer! one more question when i submit my form value of select all (0) is submitted in json array, how can i remove it and submit form with other options value? – zaqwsx Feb 18 '21 at 17:55
  • Not sure how your form is set up, but in my StackBlitz the form field value contains 0 as well as the other values when "Select All" is ticked. If that's the same for you, you can remove the 0 by doing `this.branch.value.filter(v => v !== 0)` Have a look at the `submit()` function in [this StackBlitz](https://stackblitz.com/edit/angular-r9tkqx-7ativn?file=src%2Fapp%2Fselect-multiple-example.ts) which is called when you click the Submit button – Ian A Feb 19 '21 at 08:50