Implementing Angular's Advanced Filtering Across Multiple Data Fields

I am looking to create a custom filter for a list. Here is an example of the Array of Objects:

myList: [
  {
    "id": 1,
    "title":"title",
    "city":"city name",
    "types":[
      {
        "id":1,
        "name":"type 1 name"
      },
      {
        "id":2,
        "name":"type 2 name"
      }
    ],
    "properties": [
      {
        "id": 1,
        "name": "prop 1 name"
      },
      {
        "id": 2,
        "name": "prop 2 name"
      }
    ]
  },
  {
    "id": 2,
    "title":"title2",
    "city"":"city name",
    "types":[
      {
        "id":1,
        "name":"type 1 name"
      }
    ],
    "properties": [
      {
        "id": 2,
        "name": "prop 2 name"
      },
      {
        "id": 3,
        "name": "prop 3 name"
      }
    ]
  },
]

I have select fields with multiple options for city, type, and property.

  <form *ngIf="filterForm" [formGroup]="filterForm">
      <div class="row justify-content-start">
        <div class="col-xl-3">
          <mat-form-field appearance="outline">
            <mat-label>Filter by city</mat-label>
            <mat-select formControlName="filterCity" multiple="true">
              <mat-option *ngFor="let city of cities" [value]="city.name">{{city.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
        <div class="col-xl-3">
          <mat-form-field appearance="outline">
            <mat-label>Filter by type</mat-label>
            <mat-select  formControlName="filterAdType" multiple="true">
              <mat-option *ngFor="let type of Types" [value]="type.name">{{type.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
        <div class="col-xl-3">
          <mat-form-field appearance="outline">
            <mat-label>Filter by property</mat-label>
            <mat-select  formControlName="filterProperty" multiple="true">
              <mat-option *ngFor="let prop of Properties" [value]="prop.name">{{prop.name}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <div class="col-xl-6 text-end">
          <button mat-button color="primary" (click)='filterSet()'>set filters</button>
        </div>
        <div class="col-xl-6 text-start">
          <button mat-button color="primary" (click)='clearFilters()'>clear filters</button>
        </div>
      </div>
     </form>

The list is displayed in a table

        <table class="table table-hover"  *ngIf="myList.length > 0">
          <thead>
            <tr>
              <!-- <th scope="col">#</th> -->
              <th scope="col">Title</th>
              <th scope="col">Type</th>
              <th scope="col">Property</th>
              <th scope="col">City</th>
            </tr>
          </thead>
          <tbody>
            <tr *ngFor="let item of myList; let i = index">
              <td>
                <div>
                  <strong>{{item.title}}</strong>
                </div>
              </td>
              <td>
                <div *ngFor="let type of item.types">
                  {{type.name}}
                </div>
              </td>
              <td>
                <div *ngFor="let prop of item.property">
                  {{prop.name}}
                </div>
              </td>
              <td>{{item.city}}</td>
            </tr>
          </tbody>
        </table>

I am currently facing challenges with filtering the multiple selects, especially the properties and type arrays. The filterSet() function is currently empty.

Answer №1

To begin, it is essential to create a duplicate of the original data values using lodash cloneDeep before implementing any filters. Once the filters have been applied, use this duplicated array to filter the data displayed on the HTML page.

  filterSet() {
    this.pageList = [];
    this.pageList = this.data.filter((x: any) => {
      const { filterCity, filterAdType, filterProperty } =
        this.filterForm.value;
      return (
        (filterCity && filterCity.length
          ? filterCity.includes(x.city)
          : true) &&
        (filterAdType && filterAdType.length
          ? filterAdType.includes(x.types.name)
          : true) &&
        (filterProperty && filterProperty.length
          ? x.properties.find((item) => filterProperty.includes(item.name))
          : true)
      );
    });
  }

Thank you for sharing the stackblitz link. The issue was related to ensuring that the dropdown data names match the data in the grid!

Visit stackblitz for a working example.

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

Angular 14: Creating a Dynamic Component with NgControl as a Dependency

I am currently trying to dynamically add a component to the DOM using ViewContainerRef's createComponent method. The challenge I am facing is that the component relies on NgControl, and my ultimate goal is to incorporate these components into a form u ...

`The process of converting Typescript to ES5 through compiling/transpiling is encountering issues`

My current project involves using Webpack and integrating angular2 into the mix. To achieve this, I made adjustments to my setup in order to compile TypeScript. Following a resource I found here, my plan was to first compile TypeScript to ES6 and then tra ...

Retrieve a multitude of nested Records within the returnType that correlate with the number of arguments provided to the function

My goal is to dynamically define a deeply nested ReturnType for a function based on the number of arguments passed in the "rest" parameter. For example, if we have: getFormattedDates( dates: Date[], ...rest: string[] // ['AAA', 'BBB&apos ...

I am facing difficulty in retrieving data from Firestore using Angular

I've been utilizing the AngularFireList provided by @angular/fire/database to retrieve data from firestore. However, despite having data in the firestore, I am unable to fetch any information from it. import { Injectable } from '@angular/core&apo ...

Navigating with the InAppBrowser in Ionic Angular after a POST request

Currently, I am in the process of redirecting my app to 3DS for a payment method. According to the documentation, the steps involved are: Obtain the action.url and the action.method from the /payments response. Redirect the shopper to the specified URL us ...

What could be the rationale behind the optional chaining operator not being fully compatible with a union of classes in TypeScript?

Imagine I have a combination of classes: type X = ClassA | ClassB | ClassC; Both ClassA and ClassC have a shared method called methodY. Why is it that I can't simply use the optional chaining operator to call for methodY? class ClassA { methodY ...

Translate array into object with correct data types (type-specific method)

Welcome In our project, we have implemented attributes support where each attribute acts as a class. These attributes include information on type, optionality, and name. Instead of creating an interface for every entity, my goal is to automate this proces ...

Establish a connection between two JSON files using the WordPress REST API

I have developed an app using ionic 2 that revolves around quotes. My goal is to manage these quotes (along with authors, categories, etc) using Wordpress and its REST API. Initially, I utilized normal posts for this purpose, but now I am exploring custom ...

Currently in the process of modernizing an outdated method to a more up-to-date version in Jasmine, encountering issues related to

Currently working to update the method throwOnExpectationFailure to the newer one oneFailurePerSpec. According to the Jasmine documentation, this can be achieved by: Use the `oneFailurePerSpec` option with Env#configure After conducting research, I came ...

Angular 5: How to Calculate the Sum of Two Numbers and Handle NaN Output

I have encountered an issue where I am trying to multiply two numbers and add another number, but the output is displaying as NaN. How can I troubleshoot and solve this problem? Below is the code snippet: medicines = [new Medicine()]; this.sum = 0;// su ...

Saving information obtained through Angular subscribe into a variable

One of the services I have is called getWeather, which contains a method that communicates with an API using longitude and latitude parameters and then returns the response: import { Injectable } from '@angular/core'; import { HttpClient } from ...

Challenge with JWT Tokens

In my application, I am utilizing a Node.JS express backend along with an Angular 4 frontend. The user ID is stored in JWT tokens, which do not expire. Here is the scenario: The user logs in. A JWT Token is generated and signed (containing the user ID). ...

There seems to be an issue with the functionality of Angular Material in Angular9

I've encountered an issue with the material form field, even after importing the necessary modules. Surprisingly, there are no console errors to provide more insight into the problem. { "name": "online-shop", "version": "0.0.0", "scripts": ...

Navigating through an array in Angular 5: a guide

This question may seem simple, but I'm having trouble figuring it out. Here is the code snippet I am working with: getInstabul(): void { this.homeService.getWeather() .subscribe((weather) => { this.instanbulWeathers = weather ...

Encountering an issue with Angular 12 where a TypeError is being thrown, specifically stating "Cannot read properties of null (reading 'length') at

I encountered an error message while making a http request in my Angular Service. Strangely, this error only occurs after I logout, but it disappears upon logging back in: Below is the code snippet of my authentication Service: import { Injectable } from ...

Enhancing Request JSON Body Validation in Next.js 14 API Handler

I'm currently in the process of developing an API for my iOS application using Next.js 14. I have managed to get it up and running successfully, however, I am facing some challenges when it comes to properly validating the body of a request. ESLint is ...

Leveraging local resources to create images with the help of @vercel/og and Next.js

Utilizing the latest @vercel/og library for generating meta-tag images has been quite intriguing. The official example showcases how to leverage images from an external source. The Quandary at Hand <img src={"https://res.cloudinary.com/iqfareez ...

Displaying data from an Angular subscription in a user interface form

I am attempting to transfer these item details to a form, but I keep encountering undefined values for this.itemDetails.item1Qty, etc. My goal is to display them in the Form UI. this.wareHouseGroup = this.formBuilder.group({ id: this.formBuilder.contr ...

Function `getEventMap` that retrieves the specific "EventMap" associated with an EventTarget T

In the file lib.dom.d.ts, there is a defined interface: interface EventTarget { addEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean): void; dispatchEvent(event: Event): boo ...

How can I modify the icon once the accordion summary is expanded?

How can I switch the icon based on whether the accordion is expanded or not? I noticed that on the material ui page there is a CSS class called .Mui-expanded which can detect whether expanded={true} or false. But, how do I utilize this to change the ...