Angular's superior filtering capabilities shine through in the Material table

When using Angular, I have implemented a Material table with expanded rows and would like to filter it based on the RequestId.

table-tree.html

<div class="filter">
<span>
  <h5 class="requestid">Request ID</h5>
  <input type="text" [(ngModel)]="requestFilter" />
</span>
</div>

<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
  <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>

  <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;
  expandedInfo: MoveOrderAuthorizations;
  requestFiltered = '';

  get requestFilter(): string {
    return this.requestFiltered;
  }
  set requestFilter(value: string) {
    console.log(value);
    this.requestFiltered = value;
    this.filteredRequests = this.performFilter(value);
  }
  filteredRequests: MoveOrderAuthorizations[] = [];

  performFilter(filterBy: string): MoveOrderAuthorizations[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.dataSource.filter((request: MoveOrderAuthorizations) =>
      request.requestId.includes(filterBy));
  }

  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'
  };

  responseColumnsToDisplay = ['moveorderId', 'originDestination', 'status'];
  subColumnNames = {
    moveorderId: 'Move Order ID',
    originDestination: 'Origin Destination',
    status: 'Status'
  };

}

export interface MoveOrderAuthorizations {
  creationDate: string;
  requestId: string;
  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: '254982',
    issue: `Destination not found`,
    requestType: `Supply`,
    managedBy: `AGV`,
    serialNumberProductRefToSupply: `ML132345XO1211321AND11432002`,
    serialNumberOriginSupplyToDestination: `RE-11WIP-11E03`
  }
];

The method created for filtering the displayed data is not functioning properly. Here is the code snippet:

  performFilter(filterBy: string): MoveOrderAuthorizations[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.dataSource.filter((request: MoveOrderAuthorizations) =>
      request.requestId.includes(filterBy));
  }
  requestFiltered = '';

  get requestFilter(): string {
    return this.requestFiltered;
  }
  set requestFilter(value: string) {
    console.log(value);
    this.requestFiltered = value;
    this.filteredRequests = this.performFilter(value);
  }
  filteredRequests: MoveOrderAuthorizations[] = [];

To view the table in action, you can visit Stackblitz at the following link: [https://stackblitz.com/edit/tab-tree-filter?file=app/table-tree.ts][1]

Thank you for your attention :)

Answer №1

The main issue at hand is the usage of the datasource variable in mat-table. Instead of updating the original datasource when filtering items, a separate array named requestsFiltered is being used. This leads to the table not being updated correctly after filtering.

To address this issue, please refer to the updated code.

Changes made (based on the stackblitz code):

HTML (changed datasource to filteredRequests):

<table mat-table [dataSource]="filteredRequests" multiTemplateDataRows class="mat-elevation-z8">

TS:

  1. Initialized the requestsFiltered to match the original unfiltered datasource
  ngOnInit() {
    this.filteredRequests = this.dataSource;
  }
  1. Updated the performFilter function
performFilter(filterBy: string): MoveOrderAuthorizations[] {
    filterBy = filterBy.toLocaleLowerCase();
    this.filteredRequests = this.dataSource.filter(
      (request: MoveOrderAuthorizations) => request.requestId.includes(filterBy)
    );
    return !!filterBy && this.filteredRequests.length > 0
      ? this.filteredRequests
      : this.dataSource;
}

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 a reducer be molded in ngrx without utilizing the createReducer function?

While analyzing an existing codebase, I came across a reducer function called reviewReducer that was created without using the syntax of the createReducer function. The reviewReducer function in the code snippet below behaves like a typical reducer - it t ...

Ensure that the specified Class type must have a constructor with no arguments

When working with a function that takes a parameter representing a Class (not an object or instance, but the Class itself), or essentially a variable assigned to a Class. The challenge is ensuring that the Class assigned to the parameter has a constructor ...

What is a practice for utilizing navCtrl.push() with a variable storing a class name?

Currently, I am utilizing Visual Studio Code for Ionic 3 development with AngularJS/Typescript. In my code, I am using this.navCtrl.push() to navigate to different pages within the application. Specifically, I have two classes/pages named "level1" and "lev ...

Troubleshooting error handling in Angular HttpClient proves to be quite

The Angular documentation regarding the new HttpClient can be found at https://angular.io/guide/http. Within this documentation, there is a section titled "Getting error details" which provides an example similar to the one displayed below. I have made mod ...

Can a TypeScript function be structured to return never (or throw) if a generic type extends a subtype without requiring casting?

(This code snippet is purely for demonstration purposes, as no real use-case exists here) I am attempting to create a function that throws an error if the input string is equal to "fish". I have achieved this using the as keyword, but I am curious if ther ...

Error: Idle provider not found in the promise

Currently, I am integrating ng2-idle into an AngularJS 2 application. After successfully including the ng2-idle package in the node_modules directory of my project, I attempted to import it into one of my components as shown below: Dashboard.component.ts: ...

What is the best way to choose the option with the highest value?

<option *ngFor="let value of filterItem.values" [(value)]="value.code" [selected]="value.default_ind == Math.max(...filterItem.values.map(item => item.default_ind))" required>{{value.displayName}}</option> I am working with these options, ...

Angular 6: Effectively Triggering the Active Button Among Multiple Buttons Sharing the Same Function Name

I'm facing an issue with a button that toggles the visibility of a password field. I named all the show/hide buttons with the same function, but now when I click on one specific button, it triggers all the textboxes instead of just the current one. H ...

How to pass a String Array to a String literal in JavaScript

I need to pass an array of string values to a string literal in the following way Code : var arr = ['1','2556','3','4','5']; ... ... var output = ` <scr`+`ipt> window.stringArray = [`+ arr +`] & ...

TypeScript's reliance on dependent types

Is it possible to implement this functionality using TypeScript? There exist objects that define various "actions". export interface IAction { action: string; data: any; otherParam1: number; otherParam2: number; } The 'action' p ...

What causes compilation errors while attempting to integrate Angular elements into a Material Dialog component?

I attempted to set up a basic Angular application with a Material Dialog, but encountered difficulties when trying to include any Angular-specific elements in the HTML of the dialog (such as using <mat-dialog-content> or [(ngInput)]), resulting in co ...

Angular is facing an issue with Canvas DataGrid because it cannot locate the /dist/types.d.ts file

I've been encountering an error while trying to implement canvas-datagrid in my angular project. I've attempted various solutions like deleting node_modules and package.lock.json, but the issue persists. node_modules/canvas-datagrid/dist/types.d. ...

What causes the return value of keyof to vary in this particular case?

type AppleNode = { type: 'Apple' name: string score: number } type BananaNode = { type: 'Banana' id: number score: number } type FruitNodes = AppleNode | BananaNode type fruitTest = { [P in keyof FruitNodes]: 21 } // Th ...

Can an ES6 class be utilized as a custom TypeScript type?

My goal is to accomplish the following: Developing a Typescript class and exporting it in a .ts file. Compiling that .ts file into an ES6 .js bundled file. Importing the class from the bundled .js file in a new .ts file elsewhere. Utilizing this imported ...

Angular 4 - Custom global error handler fails to capture Http errors

I have implemented a global event handler in my Angular application: import { ErrorHandler, Injectable, Injector } from '@angular/core'; import { Router } from '@angular/router'; @Injectable() export class GlobalErrorHandler implements ...

What happens when you create a Union type alias between two connected interfaces?

Recently, I encountered a peculiar situation that left me puzzled as I scoured the internet and documentation for answers but found none. Let's delve into the following scenario: interface A { foo: string; bar: string; } interface B extends ...

Angular 6 does not allow assigning a parameter of type 'void' to a parameter of type 'string' in arguments

Angular Component Function onFileChangedForCV(event) { this.details.= event.target.files[0] } candidateDetails() { let formData = new FormData(); let photo= formData.append('profile_pic',this.details.photo); let name=this.detai ...

What is the code to continuously click on the "Next" button in playwright (typescript) until it is no longer visible?

Currently, I have implemented a code that clicks the next button repeatedly until it no longer appears on the pagination. Once the last page is reached, I need to validate the record. The problem arises when the script continues to search for the locator ...

`The nginx docker image is experiencing issues with the `try_files` directive

I have a straightforward Angular single-page application that I am attempting to host using the Nginx docker image, version 1.17.1. Within my Dockerfile, I first build and package Angular before transferring the resulting files to the nginx image. FROM n ...

How can I import multiple variables in TypeScript?

I have a React application built with TypeScript, and my project directory is structured as follows: App.tsx /pages Page1.tsx The contents of Page1.tsx are shown below: Page1.tsx class PageParams { constructor() { } } class Page1 { co ...