What is the best way to apply wildcard filtering to a MatTableDataSource?

I found inspiration in the Table with filtering example on Angular Material's website, which can be accessed at https://material.angular.io/components/table/examples

My goal is to enable users to search using wildcards. For instance, I want to use a % as a wildcard character.

This is what I came up with:

    const filterValue = (event.target as HTMLInputElement).value;

    let filterArray = filterValue.trim().toLowerCase().split("%");

    for (let fil of filterArray) {
      //Although I understand that this line below won't work, since it will simply replace the filter with each iteration, I include it here for demonstration purposes
      this.tableData.filter = fil;
      
    }

Therefore, if the user inputs one%two into the input field, I expect the filter to locate table rows where both "one" and "two" appear somewhere within the row.

I have experimented with various code iterations, but none seem to provide the desired outcome. Do you have any suggestions on how I can successfully implement this functionality?

Answer №1

To implement a custom filter logic, you will need to modify the default behavior of this.dataSource.filterPredicate in the following manner:

constructor() {
    this.dataSource.filterPredicate = ((data, filters) => {
      let match = false;
      const filtersList = JSON.parse(filters);

      filtersList.forEach(filterObj => {
        match =
          match || !filterObj ||
          Object.values(data)
            .map(t => t.toLocaleString().toLocaleLowerCase())
            .includes(filterObj);
      });
      return match;
    }) as (PeriodicElement, string) => boolean;
  } 

In your applyFilter method, ensure that you pass an array to the filterPredicate using JSON.stringify(filterArray); like so:

applyFilter(filterValue: KeyboardEvent) {
    let filterArray = (filterValue.target as any).value
      .trim()
      .toLowerCase()
      .split('%');
    this.dataSource.filter = JSON.stringify(filterArray);
  } 

You can find a complete working example that I created for you here.

https://i.sstatic.net/HREzy.png

Answer №2

By implementing the code below in my applyFilter() method, I was able to successfully achieve my goal:

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;

    let filterArray = filterValue.trim().toLowerCase().split("%");

    let filteredData = [];

    // Iterate through each word in the filter and add matching arrays from the dataset to filteredData
    for (let str of filterArray) {
      filteredData.push(
        this.data.filter((o) =>
          Object.keys(o).some((k) => String(o[k]).toLowerCase().includes(str))
        )
      );
    }

    // Narrow down final dataset with array items that appear in all arrays produced by each search term
    filteredData = filteredData.reduce((a, b) =>
      a.filter((c) => b.includes(c))
    );

    this.tableData.data = filteredData;
  }

The solution I came up with was influenced by insights gathered from the following questions:

  • Filter array of objects based on property values

  • Calculating intersection of multiple arrays in JavaScript

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

What is the best way to disable a submit button based on form validity in Angular 4 with ng-content?

Include a form component that consists of an email field, password field, and submit button passed through ng-content. This allows the login form to display a 'Login' button and the register form to display a 'Register' button. Here is ...

Looking to transform a psql query into typeorm syntax

I am in search of data on a daily, weekly, or monthly basis. I utilized the date_trunc() function to generate such records. Although I was successful in creating a psql query, I am unfamiliar with typeorm stack and need guidance on converting it into typeo ...

How can Spring Boot be used to format time and save it in the database using the HH:mm format instead of the default HH:mm:ss format?

I'm currently working on a project that involves a spring boot/angular application, and I am facing an issue with sending a time attribute to my REST API in a specific format. I need to send the time in "HH:mm" format instead of the default "HH:mm:ss" ...

The Environment variable in React Native is not functioning when utilizing TypeScript

After installing the react-native-dotenv library, I followed the instructions outlined in the TypeScript guide. I then created a .env file with the following contents: MARVEL_API = <url> MARVEL_PUBLIC_KEY = <public-key> MARVEL_PRIVATE_KEY = &l ...

Error: Value Loop Detected in AngularFire Document ID

I encountered a "Cyclic Object Value" Error while working on an Angular Project with AngularFire. As a beginner with Firebase, I haven't been able to find a straightforward solution to this issue. The error arises when I query a collection in my Fire ...

What is the most efficient method to retrieve an API in Angular?

Recently, I dedicated some time to a personal Angular project. While working on it, I decided to experiment with making an API call to PokeAPI in order to retrieve the .svg image of a Pokemon along with its name. After successfully implementing this featur ...

Arranging an array of arrays based on the mm/dd/yyyy date field

Currently, I am facing an issue while attempting to sort data obtained from an API by date in the client-side view. Here is an example of the data being received: address: "1212 Test Ave" address2: "" checkNumber : "" city: "La Grange" country: "" email: ...

Having difficulty resolving all parameters for the component: (?, [object Object]) in the Jasmine component Unit Test

While defining a UT for a component with an extended class using i8nService and ChangeDetectionRef, I encountered an error preventing me from instantiating it: Failed: Can't resolve all parameters for BrandingMultiselectComponent: (?, [object Object] ...

Steps to establish a maximum font size for my buttons

I've been working on creating buttons to decrease and increase the font size of my text. The functionality is there, but I want to establish a limit on how small or large the font can go. Here's what my current code looks like: <md-button ng ...

How to stop a form from being cleared when a button is clicked in Angular 2

Within my form, there is a button that allows users to add an item to the object's array. <form (ngSubmit)="submit()" #myForm="myForm" class="form-horizontal" style="direction: ltr"> <div class="row"> <div class="col-md-6"> ...

Install a MEAN Stack application on the server of my choosing

My MEAN Stack app is running smoothly in development mode. I am now looking to deploy it on my company's server, but I am struggling to find resources on deploying MEAN apps on a server of my choice. Most of the tutorials I found focus on platforms li ...

Encountering problem with '@datadog/browser-rum' compilation related to the 'allowedTracingOrigins' attribute

I'm facing a typing problem with the @datadog/browser-rum library: Error: node_modules/@datadog/browser-rum-core/src/domain/configuration.ts:100:3 error TS2322: Type '{ applicationId: string; version: string; actionNameAttribute: string; premium ...

Issues with Firebase Cloud Messaging functionality in Angular 10 when in production mode

Error: Issue: The default service worker registration has failed. ServiceWorker script at https://xxxxxx/firebase-messaging-sw.js for scope https://xxxxxxxx/firebase-cloud-messaging-push-scope encountered an error during installation. (messaging/failed-ser ...

Calculate the variance between two variables

I am facing a challenge where I have an object and the 'Hours' field is saved as a string. I am looking to convert this string into actual hours and then calculate the difference between the two variables. const groupSchedule=[ {"days":"sat" ...

Ways to effectively implement a function type specified in an interface

Consider the following interface: interface MyProps { onEvent: (name: string, data: any) => void; } Is there a way to utilize the function type in order to avoid unused parameter errors during compilation? eventHandler = (name: string, data: any) = ...

Ionic Angular encountered an unexpected 'ERROR' without any detailed explanation or logging

https://i.sstatic.net/aJPD1.png Hey there, I'm encountering some issues with my Ionic App. Currently, I am executing ionic cordova run android --livereload --consolelogs --serverlogs using a physical device. Although I can see console.logs, there ...

Obtain the current state of an Angular Material radio button that has been selected

I am currently working with an Angular Material mat-table that has columns for checkboxes and rows, using Material components for each. Extracting the selected state of the checkbox is straightforward with row.checked, as demonstrated below. However, I am ...

Is there a way to activate the final form when submitted?

I am facing an issue with React Final Form. Despite following the example in the official documentation, I am still struggling to understand why my form is not triggering the onSubmit function as in the example. I am also grappling with understanding the p ...

What are the steps to incorporate a type-safe builder using phantom types in TypeScript?

In order to ensure that the .build() method can only be called once all mandatory parameters have been filled, it is important to implement validation within the constructor. ...

Ensure the clarity tabs labels have the padding-left CSS property added

In my project, there are 2 clarity tabs (you can view the StackBlitz reference here). https://i.sstatic.net/jhLcn.png I want to apply the padding-left property specifically to Tab1 (the tab label itself, not the content) in order to create some space aro ...