Angular is a powerful framework that enables the creation of dynamic user interfaces. One of its many

Looking to implement a Material table with expandable rows in Angular.

table-tree.html

<table
  mat-table
  [dataSource]="dataSource"
  multiTemplateDataRows
  class="mat-elevation-z8"
>
  <ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
    <th mat-header-cell *matHeaderCellDef>{{column}}</th>
    <td mat-cell *matCellDef="let element"&grm;
      <tr>{{element.creationDate}}</tr>
      <tr>{{element.requestId}}</tr>
    </td>
  </ng-container>

  <ng-container matColumnDef="expandedDetail">
    <td
      mat-cell
      *matCellDef="let element"
      [attr.colspan]="columnsToDisplay.length"
    >
      <div
        class="example-element-detail"
        [@detailExpand]="element == expandedInfo ? 'expanded' : 'collapsed'"
      >
        <div class="example-element-position">{{element.creationDate}}</div>
        <div class="example-element-description>
          {{element.serialNumberProductRefToSupply}}
        </div>
        <div class="example-element-description">
          {{element.serialNumberOriginSupplyToDestination}}
        </div>
      </div>
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr
    mat-row
    *matRowDef="let element; columns: columnsToDisplay;"
    class="example-element-row"
    [class.example-expanded-row]="expandedInfo === element"
    (click)="expandedInfo = element"
  ></tr>
  <tr
    mat-row
    *matRowDef="let row; columns: ['expandedDetail']"
    class="example-detail-row"
  ></tr>
</table>

table-tree.ts

import { Component } from '@angular/core';
import {
  animate,
  state,
  style,
  transition,
  trigger
} from '@angular/animations';

@Component({
  selector: 'table-tree',
  styleUrls: ['table-tree.css'],
  templateUrl: 'table-tree.html',
  animations: [
    trigger('detailExpand', [
      state(
        'collapsed',
        style({ height: '0px', minHeight: '0', display: 'none' })
      ),
      state('expanded', style({ height: '*' })),
      transition(
        'expanded <=> collapsed',
        animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
      )
    ])
  ]
})
export class TableTree {
  dataSource = MoveOrderData;
  columnsToDisplay = [
    'Creation Date',
    'Request ID',
    'Issue',
    'Request Type',
    'Managed by',
    'Product ref to supply',
    'Origin supply to Destination'
  ];
  
  rowsToDisplay = [
    'creationDate',
    'requestId',
    'issue',
    'requestType',
    'managedBy',
    'serialNumberProductRefToSupply',
    'serialNumberOriginSupplyToDestination'
  ];
  expandedInfo: MoveOrderAuthorizations;
}

export interface MoveOrderAuthorizations {
  creationDate: string;
  requestId: number;
  issue: string;
  requestType: string;
  managedBy: string;
  serialNumberProductRefToSupply: string;
  serialNumberOriginSupplyToDestination: string;
}

const MoveOrderData: MoveOrderAuthorizations[] = [
  {
    creationDate: `01/01/2021`,
    requestId: 139322,
    issue: ``,
    requestType: `Evacuation`,
    managedBy: `AGV`,
    serialNumberProductRefToSupply: `ML132345XO1211321AND11432001`,
    serialNumberOriginSupplyToDestination:`SA-11EOL-LN001`
  },
  {
    creationDate: `01/01/2021`,
    requestId: 139323,
    issue: `Destination not found`,
    requestType: `Supply`,
    managedBy; `AGV`,
    serialNumberProductRefToSupply: `ML132345XO1211321AND11432002`,
    serialNumberOriginSupplyToDestination: `RE-11WIP-11E03`
  }
];

In table-tree.ts, there are defined arrays for the columns and rows data.

  columnsToDisplay = [
    'Creation Date',
    'Request ID',
    'Issue',
    'Request Type',
    'Managed by',
    'Product ref to supply',
    'Origin supply to Destination'
  ];
rowsToDisplay = [
    'creationDate',
    'requestId',
    'issue',
    'requestType',
    'managedBy',
    'serielNumberProductRefToSupply',
    'serialNumberOriginSupplyToDestination'
  ];

Despite initial difficulties, progress is being made but some issues remain unresolved. Feel free to check out the code on Stackblitz > https://stackblitz.com/edit/tab-tree?file=main.ts

Your support is greatly appreciated! :)

Answer №1

It is advisable to use your datasource field names as your column names. Consider renaming rowsToDisplay to columnsToDisplay and creating a new object called columnNames:

  columnsToDisplay = [
    'creationDate',
    'requestId',
    'issue',
    'requestType',
    'managedBy',
    'serialNumberProductRefToSupply',
    'serialNumberOriginSupplyToDestination'
  ];

  columnNames = {
    creationDate: 'Creation Date',
    requestId: 'Request ID',
    issue: 'Issue',
    requestType: 'Request Type',
    managedBy: 'Managed by',
    serialNumberProductRefToSupply: 'Product ref to supply',
    serialNumberOriginSupplyToDestination: 'Origin supply to Destination'
  };

Update your template to utilize the columnsToDisplay array for fetching values from your datasource:

  <ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
    <th mat-header-cell *matHeaderCellDef>{{columnNames[column]}}</th>
    <td mat-cell *matCellDef="let element">
      {{element[column]}}
    </td>
  </ng-container>

Visit this link for more information.

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

Error encountered when attempting to locate the file declaration for module 'jwt-decode'

Currently, I am utilizing the Visual Studio 2017 template for my Angular project and encountering an issue when attempting to import the 'jwt-decode' module after adding it to package.json. The error (mentioned in the title of my post) arises aft ...

Customizing the choices for an ActionSheet on Ionic 2 on the fly

After making a GET request, I receive JSON data containing an array of options with id, style, and name for each element. I need to dynamically populate the options in my ActionSheet within my Ionic 2 app based on this API response. The ActionSheet is fu ...

Sending a message to an iframe from a different origin using JavaScript

Just starting out with JavaScript and I'm attempting to send a message to my iframe in order to scroll it. Here is the code I am using: scroll(i) { var src = $("#iframe").attr("src"); $("#iframe").contentWindow.postMe ...

Inserting a pause between a trio of separate phrases

I am dealing with three string variables that are stacked on top of each other without any spacing. Is there a way to add something similar to a tag in the ts file instead of the template? Alternatively, can I input multiple values into my angular compo ...

Resolving Hot-Reload Problems in Angular Application Following Upgrade from Previous Version to 17

Since upgrading to Angular version 17, the hot-reload functionality has been causing some issues. Despite saving code changes, the updates are not being reflected in the application as expected, which is disrupting the development process. I am seeking ass ...

Updating a particular element within an array in Firestore

Hello everyone, I'm currently working with Google Firestore and Angular. I am facing a challenge where I need to update a particular element within an array. I have experimented with various solutions but unfortunately, none of them have been success ...

What could be the reason it's not functioning as expected? Maybe something to do with T extending a Record with symbols mapped

type Check<S extends Record<unique, unknown>> = S; type Output = Check<{ b: number; }>; By defining S extends Record<unique, unknown>, the Check function only accepts objects with unique keys. So why does Check<{b:number}> ...

Getting Started with Angular: Loading Data into a List from a Service

As I am relatively new to Angular, I have a list that needs to be displayed on the screen. Initially, I was able to show the list with hard-coded data, but now I need to fetch the data from my service that calls an API. The data retrieval part is already i ...

When creating a responsive datatable in Angular, be aware that the reference to "this.table

Here is the code from my datatable.component.ts: import { Component,AfterViewInit, OnDestroy,ElementRef, ViewChild, OnInit } from '@angular/core'; declare var $; import { Http, Response } from '@angular/http'; import { Subj ...

What is the best way to access DirectivesModule from a component that utilizes specific directives within it?

Updated: After thorough consideration, it has come to light that the efficient solution involves importing SharedModule into the parent component of the child component utilizing the DropDownDirective for proper functionality. Delving into an Angular 4 ...

Deactivating AngularJS debug information in a gulp / typescript production compilation

What is the most effective approach to disabling debug data in a gulp production build? The recommended method for disabling debug data is: myApp.config(['$compileProvider', function ($compileProvider) { $compileProvider.debugInfoEnabled(false ...

Whenever I try to update my list of products, I encounter an error message stating that the property 'title' cannot be read because it is null

I am encountering an issue with editing data stored in the database. When attempting to edit the data, it is not displaying correctly and I am receiving a "cannot read property" error. HTML admin-products.component.html <p> <a routerLink="/ad ...

Is there a way to expand the color options of mui using Typescript?

I'm attempting to expand the color options provided by mui. While overriding primary, secondary, and other preset colors works smoothly, I'm struggling with creating a custom set of colors right after. Despite numerous examples available without ...

Sending a POST request that is attempting to insert empty values into an MS SQL database

Here is the code I am working with - onSubmit(){ var headers = new Headers(); headers.append('Content-Type', 'application/x-www-form-urlencoded'); let postParams = { firstName : this.firstName, lastName : this.lastNa ...

Issues with FormsModule functioning incorrectly when used in a separate module other than the main App Module

Within my SharedModule, I have the FormsModule imported. import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from &ap ...

Introducing NextAuth: Empowering multiple users to access a single account

I've been pondering if it's possible to have multiple users for a single account provider. One idea is to create a session with a specific field indicating the active user (the one currently logged in) and then allow for easy switching between us ...

Merging declarations fails to function properly following the release of the npm module

The file core.ts contains the definition of a class called AnyId. In another file named time.ts, more methods are added to the AnyId class. This is achieved by extending the type of AnyId using declaration merging: declare module './core' { in ...

Guide on Implementing Link href in Next.js v12

When I set the href as a string, the link functions properly. However, when I use an object for the href, the link fails to work. Despite seeing the correct querystring when hovering over the link, it always takes me back to the first page. // ProdCard t ...

Tips for emphasizing active tabs in Angular 6

**I have everything displaying perfectly, but I am wondering how to highlight the active tab without using any third-party components. Any assistance would be greatly appreciated. Thank you.** <ul class="tabs"> <li [ngClass]=" {'active-tab ...

changing an array into json format using TypeScript

Looking to convert an array into JSON using TypeScript. How can I achieve the desired result shown below? let array = ['element1', 'element2', 'element3'] result = [{"value": "element1"}, {"value": "element2"}, {"value": "el ...