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

Why is it that my side effect action is unable to identify the return action type property?

I've been working on setting up SideEffect for my authentication store, but every time I trigger the action (TrySignIn), I keep encountering this error: "AuthEffects.authSignin" dispatched an invalid action ERROR TypeError: Actions must hav ...

Tips on deactivating a div when a checkbox is selected

I am currently working with a checkbox element in my code: <md-checkbox checked.bind="addEventCommand.allDay" change.delegate="allday()">All Day</md-checkbox> When the above checkbox is true, I want to disable the following ...

Typescript: Potential null object error when defining a method

I recently encountered an error message stating "Object is possibly null" while working on the changePageSize method in book-store.component.html. It seems like I need to initialize the object within the class, but I'm not familiar with how to do that ...

Struggling to retrieve posted data using Angular with asp.net

I have encountered an issue while sending a post request from Angular to my ASP.NET server. I am trying to access the values of my custom model class (SchoolModel) and I can see that all the values are correct inside Angular. However, when I attempt to ret ...

Discovering various kinds of data with a single generic type

I am looking to define a specific type like this: type RenderItems<T> = { [K in keyof T]: { label: string; options: { defaultValue: T[K]['options'][current_index_of_array]; item: (value: T[K][&apo ...

Understanding how to infer literal types or strings in Typescript is essential for maximizing the

Currently, my goal is to retrieve an object based on the parameter being passed in. I came across a similar question that almost meets my requirements. TypeScript function return type based on input parameter However, I want to enhance the function's ...

The operation failed with a TypeError because the object does not allow the addition of the newField property

I encountered an error that says: TypeError: Cannot add property newField, object is not extensible Whenever I try to add a new key or change a value, it doesn't work and I'm not sure what the issue is. dynamicFilter; public ionViewWillEnte ...

Tips for dealing with strong reference cycles in TypeScript?

I have created a tree-like structure in my implementation, consisting of parent and child objects. The parents contain a list of children while the children have references to their parents, facilitating easy navigation through the tree. I am now contempla ...

What could be causing my Angular app to be unable to locate the embedded component?

This particular component is called HomeTabComponent and it is embedded here. @Component({ selector: 'app-home-tab', templateUrl: './home-tab.component.html', styleUrls: ['./home-tab.component.scss'] }) export class Ho ...

Error: Unable to locate binding.gyp file

I'm currently in the process of setting up the required modules for my web application. As I execute $npm install, an error message pops up: john@mylaptop frontend % npm install > <a href="/cdn-cgi/l/email-protection" class="__cf_ ...

React Component not displaying properly when used inside a map iteration

I am currently working on rendering multiple components using the .map method on an array with specific content. Although I can't find any errors in the console, the component is not appearing in the DOM as expected. I attempted to set subHeader to nu ...

The functionality of Layout.tsx is inconsistent across various pages

I'm having trouble with the console.log() code to display the page path only showing up in the "pages.tsx" file (src/app/pages.tsx) and not appearing in the console for other files located in (src/page/Login). Here is the code from layout.tsx: ' ...

Updating Key-Value pairs in an ArrayList using Angular 4

After importing json data into an arrayList and storing it in local-storage, the structure looks like this: [ { "id": 1, "name": "Albany", "manufacture": "Albany Superior Low Gi Sliced Brown Seed Bread 700g", "price": 1 ...

Is there a way to transfer innerHTML to an onClick function in Typescript?

My goal is to pass the content of the Square element as innerHTML to the onClick function. I've attempted passing just i, but it always ends up being 100. Is there a way to only pass i when it matches the value going into the Square, or can the innerH ...

Ways to conditionally display a component in Next.js without the issue of caching CSS styles

I'm a newcomer to Next.js and I'm still trying to wrap my head around how the caching works. Let's take a look at this simplified example: An index page that displays either Test1 or Test2 components, based on whether the current minute is ...

Issue with Formik compatibility in Next JS 14 Application Structure

I attempted to create a basic validation form using Formik. I meticulously followed their tutorial and example, but unfortunately, the form is not functioning correctly. Despite my efforts, I have been unable to identify a solution (Please correct me if I& ...

Exploring the syntax of typescript when using createContext

Just starting out with typescript and I have some questions. Could someone break down the syntax used in this code snippet for me? What is the significance of having two groups containing signIn, signOut, and user here? Is the first group responsible fo ...

The designated apiUser.json file could not be located within the _http.get() function

It's puzzling why my URL isn't working in _http.get('app/api/apiUsers') for Angular version 4.0.0, when it functions correctly in Angular version 2.3.1. The code is identical in both Angular versions: import { Injectable } from ' ...

Utilize the datasource.filter method within an *ngFor loop

I have a table that filters based on certain search criteria, which I implemented using the example found at: https://material.angular.io/components/table/examples Now, I am wondering if it is possible to apply this filtering functionality to an *ngFor lo ...

Inspecting tRPC routing for examination purposes

Introduction Within my API, it is essential to authenticate the caller following input validation. The authorization for certain endpoints relies on details provided in the input parameters, such as the specific server-side resource being accessed and the ...