Trouble with expanding multiple rows in an Angular nested mat table functionality

I recently built a nested mat-table grid using Angular Material. However, I am facing an issue where only one row can be expanded at a time. I am looking for a solution to allow multiple rows to be expanded simultaneously without automatically collapsing the previously expanded row.

If you want to see the code in action, check out the Nested Table on Stackblitz: https://stackblitz.com/edit/angular-nested-mat-table

I attempted to achieve this by pushing elements to the ExpandedElement Array, but unfortunately, it did not produce the desired results. Here is the code snippet I tried:

const index = this.expandedElements.findIndex(x => x.name == row.name);
if (index === -1) {
  this.expandedElements.push(row);
} else {
  this.expandedElements.splice(index, 1);
}

If anyone has any insights or suggestions on how to implement multiple row expansion in this scenario, I would greatly appreciate the assistance.

Answer №1

The collapse and expand functionality mirrors the approach used in the response to the question posed in How can I expand multiple rows in a Mat Table by clicking on a row in Angular?.

Key Concepts (TL;DR)

  1. Utilize the toggleElement function to add element to expandedElement.
  2. Use the isExpanded function to determine if element exists in expandedElement.
  3. Display the element (expanded/collapsed) based on the outcome of isExpanded.

PROBLEM SOLVING

Previous Approach

<div class="example-element-detail" *ngIf="element.addresses?.data.length" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
  <div class="inner-table mat-elevation-z8" *ngIf="expandedElement">
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;" [class.example-element-row]="element.addresses?.data.length"
     [class.example-expanded-row]="expandedElement === element" (click)="toggleRow(element)">
</tr>

By adding the element to expandedElements to indicate an expanded state, you must ensure the element is present in expandedElements by using isExpanded(element).

Updated Approach

<div class="example-element-detail" *ngIf="element.addresses?.data.length" [@detailExpand]="isExpanded(element)">
  <div class="inner-table mat-elevation-z8" *ngIf="isExpanded(element)">
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;" [class.example-element-row]="element.addresses?.data.length"
     [class.example-expanded-row]="isExpanded(element)" (click)="toggleRow(element)">
</tr>

.component.ts

export class TableExpandableRowsExample {

  ...

  expandedElements: any[] = [];

  ...

  toggleRow(element: User) {
    element.addresses && (element.addresses as MatTableDataSource<Address>).data.length 
      ? this.toggleElement(element) 
      : null;
    this.cd.detectChanges();
    this.innerTables.forEach((table, index) => (table.dataSource as MatTableDataSource<Address>).sort = this.innerSort.toArray()[index]);
  }

  isExpanded(row: User): string {
    const index = this.expandedElements.findIndex(x => x.name == row.name);
    if (index !== -1) {
      return 'expanded';
    }
    return 'collapsed';
  }

  toggleElement(row: User){
    const index = this.expandedElements.findIndex(x => x.name == row.name);
    if (index === -1) {
      this.expandedElements.push(row);
    } else {
      this.expandedElements.splice(index, 1);
    }
  }
}

See Sample Solution on StackBlitz

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you provide information on the latest stable release of animations for Angular 4?

Encountering an error during npm install Warning - @angular/[email protected] requires a peer of @angular/[email protected] but none was installed. Error encountered during npm start Issue with node_modules/@angular/platform-browser/animations ...

Is there a method in Angular to restrict change detection to only the current component and its descendant components?

Is there a way to trigger an event in the child component without traversing the entire component tree from the parent? import { Component } from '@angular/core' @Component({ selector: 'my-app', template: '<b>{{ te ...

Prevent authenticated users in Angular2 from accessing certain routes

In the main.ts file, I have defined a set of routes: const routes: RouterConfig = [ { path: '', component: HomeComponent }, { path: '', redirectTo: 'home', terminal: true }, { path: 'dashboard', component: Das ...

What is the best way to retrieve a service response prior to component initialization in Angular 4?

My service sends a request to an API, and based on the response, I need to decide whether a component should be loaded or not. However, due to the delay in receiving the response, the component loads regardless of the response status. After about 0.5 secon ...

Navigating the missing "length" property when dealing with partial functions generated using lodash's partialRight

I've been utilizing MomentTimezone for time manipulation within the browser. My development stack includes TypeScript and Lodash. In my application, there is an accountTimezone variable set on the window object which stores the user's preferred ...

Tips for emphasizing the currently pressed button element when clicked in Angular 2?

Here is the code snippet I am currently working with: <button *ngFor="let group of groupsList" attr.data-index="{{ group.index }}" (click)="processGroups(group.index)">{{ group.title }}</button> I am trying to figure out if it is possible to ...

Angular 2 form validation allowing submission to continue despite tag errors

Here is the code snippet provided: <form #theForm="ngForm" novalidate> <div *ngIf="pickUpAddress.cannotVerify"> <div class="form-group"> <sh-manual-address [(ngModel)]="pickUpAddress" #manualAddress="ngModel" [address]="pickU ...

Data is not being stored in the Firebase database

Currently, I am immersed in a project that involves Angular and Firebase. The main hurdle I am facing revolves around uploading data to the Firebase database. Here is a snippet of my FirebaseService Code. import { AngularFirestore } from 'angularfire ...

What are some strategies for exporting methods without resorting to the use of import * as ...?

Imagine having a file structured like this: // HelperFunctions.ts export const dateFormat = 'MM/DD/YYYY'; export const isEmpty = (input: string | null | undefined): boolean => { if (input == null) { return true; } if (!in ...

I encountered an issue while generating a crypto address on the Waves blockchain using the @waves/waves-crypto library in TypeScript

Encountering an issue with finding "crypto-js" in "@waves/waves-crypto". Despite attempts to uninstall and reinstall the module via npm and importing it using "*wavesCrypto", the error persists within the module's index.d.ts file. I am attempting to ...

Retrieve the runtime configuration object or file using Jest

Is there a way to access the Jest runtime config object or file path? I wanted to utilize runtime config properties in my custom matchers. // ./jest.config.js const path = require("path"); module.exports = { prop1: "foo", prop2: "bar" }; // my-custo ...

Issue updating @angular/core in Angular CLI caused by rxjs dependency

Currently, I am in the process of updating angular and angular material to version 6. I have successfully updated the cli to allow for the new ng update command. However, when attempting to use it to update @angular/core, I encounter an error stating that ...

Angular: Comparing the Performance of Switch Statements and Dictionary Lookups

Having trouble deciding between two options for parsing URL parameters? Both seem suboptimal, but is there a better way to handle this situation? If you have any suggestions for a plausible Option #3, please share. Let's assume we are dealing with up ...

Express: issue retrieving numbers from request body array

JavaScript / TypeScript Issue: export const updateSettings = catchErrors(async (req, res) => { console.log("updateSettings req.body: ", req.body) const { organizationId, formdata, updatedItems, updateQuota } = req.body; console.lo ...

Guide on assigning JSON response values to TypeScript variables in Angular 4

I'm just starting with Angular 4 and I'm attempting to retrieve a JSON value using http.post. The response I'm receiving is: {"status":"SUCCESS"} component onSubmit(value: any) { console.log("POST"); let url = `${this.posts_Url}`; t ...

Troubleshooting issues with Docker and Angular 2: unable to retrieve data

We are in the process of setting up an Angular 2 application with Docker by following a tutorial available at: https://scotch.io/tutorials/create-a-mean-app-with-angular-2-and-docker-compose Although the application deploys successfully, we encounter an i ...

To subscribe to the display of [Object Object], you cannot use an *ngIf statement without being inside an *ngFor loop

In my angular Quiz project, I have a functionality where every user can create quizzes. I want to display all the quizzes that a logged-in user has completed. Here is how I attempted to achieve this: // Retrieving user ID and category ID inside Re ...

Angular does not support custom validation as effectively as other frameworks

I am encountering an issue with my Angular form builder where I cannot determine the type of a file after reading it in my custom validation. Here is the link to the code on StackBlitz: https://stackblitz.com/edit/angular-ivy-atwqqc?file=src%2Fapp%2Fapp. ...

Launching the API using Modal in Angular 6

I'm seeking assistance on how to trigger a delete API request after confirming in a modal dialog using Angular. onDelete(id: number) { this.confirmationDialogService.confirm('Confirm Delete', 'Do you really want to delete this ...

The TypeScript function was anticipating one argument, however it received two instead

Can you help me fix the issue with my createUser() function? Why am I unable to pass parameters in Smoke.ts? Login.ts : interface User { url: string, email: string, } class Test{ async createUser(user: User) { await Page.setUrl(user.url); aw ...