angulartypescriptangular-material

Expand All/Collapse All column in Angular Material


I want to be able to make the Actions column on the data table to have the ability to expand and collapse all of the rows. Is there a way to do that. I am trying to make it a link but not sure how to do that or if that is possible. This the code for the Actions column.

 <ng-container
matColumnDef="{{column}}"
*ngFor="let column of columnsToDisplay"
>
 <ng-container *ngIf="column !== 'action'; else action">
  <th mat-header-cell *matHeaderCellDef>{{column}}</th>
  <td mat-cell *matCellDef="let element">{{element[column]}}</td>
 </ng-container>
 <ng-template #action>
 <th mat-header-cell *matHeaderCellDef><a href="#" (click)="accordion().openAll()"   underline="none">Actions</a></th>
  <td mat-cell *matCellDef="let element" class="checkbox-spacing">
    <mat-icon
      (click)="expandedElement = expandedElement === element ? null : element"
      >{{expandedElement === element ? 'expand_less' :
      'expand_more'}}</mat-icon
     >
   </td>
  </ng-template>
  </ng-container>

Demo code is here


Solution

  • Currently, your expand/collapse feature only support for single item. For expand/collapse all, you should revamp it to store (multiple) element(s) that is toggled for expand.

    Concept:

    1. Store expanded element(s) as an array.
    2. Toggle expand/collapse single element function.
    3. Toggle expand/collapse all function.
    4. Flags for checking single element, all elements are expanded.
    expandedElements: PeriodicElement[] | null = [];
    get isExpandAll() {
      return this.expandedElements.length == this.dataSource.data.length;
    }
    
    toggleExpandAllElements() {
      if (!this.isExpandAll) {
        this.expandedElements = [...this.dataSource.data];
      } else {
        this.expandedElements = [];
      }
    }
    
    toggleExpandElement(element: PeriodicElement) {
      const index = this.expandedElements.indexOf(element);
      if (index > -1) {
        this.expandedElements.splice(index, 1);
      } else {
        this.expandedElements.push(element);
      }
    }
    
    isElementExpand(element) {
      return this.expandedElements.indexOf(element) > -1;
    }
    

    In your view, you should pass the element to be toggled expanded/collapsed. Also, provide the element to checked whether it is expanded/collapsed.

    <mat-icon
      (click)="toggleExpandElement(element)"
    >{{isElementExpand(element) ? 'expand_less' :
      'expand_more'}}</mat-icon
    >
    
    <ng-container matColumnDef="expandedDetail">
      <td
        mat-cell
        *matCellDef="let element"
        [attr.colspan]="columnsToDisplay.length"
      >
        <div
          class="example-element-detail"
          [@detailExpand]="isElementExpanded(element) ? 'expanded' : 'collapsed'"
        >
          ...
        </div>
        <div class="example-element-name">{{element.name}}</div>
        <div class="example-element-weight">{{element.weight}}</div>
      </td>
    </ng-container>
    
    <tr
      mat-row
      *matRowDef="let element; columns: displayedColumns;"
      class="example-element-row"
      [class.example-expanded-row]="isElementExpanded(element)"
    ></tr>
    

    Demo @ StackBlitz