Angular/

How to implement multiple filters in angular using Rxjs

Published on

How to implement multiple filters in angular using Rxjs
Multiple filters in web apps now are so common, it is a must to have them. To implement multiple filters in Angular we can use Rxjs for response functionality. If we change any value it must reflect on multiple places we can achieve it using Rxjs observable to write reactive function.

Introduction :

In Angular, filters are a powerful feature that allows you to manipulate data in your application. Filters are functions that are applied to the data before it is displayed on the screen, allowing you to modify the data in various ways. Multiple filters in Angular refer to the ability to apply more than one filter to a piece of data. This allows you to create complex data manipulations that can transform the data differently. Using multiple filters, you can easily sort, filter, and transform data to meet the specific needs of your application. In this way, filters are an essential tool for working with data in Angular applications.

In addition to the built-in filters, Angular also allows developers to create their custom filters, which can be tailored to meet the specific needs of their application. Custom filters can be created using the filter service, which provides several useful methods for creating and registering filters.

Multiple filters in Angular refer to the ability to apply more than one filter to a piece of data. This allows developers to create complex data manipulations that can transform the data in many ways. For example, multiple filters can be used to sort and filter an array of data based on multiple criteria, or to format a piece of data in a specific way.


Flow Diagram :





Prerequisites :

  1. Javascript basics

  2. Angular basics


we had built a sample angular application to demonstrate the multiple filter functionality. The project code is available in GitHub for your reference use the GitHub link below for any queries.

https://github.com/episyche/angular_multiple_filters_example


Steps :

Step 1: Angular new project generate.

Create new empty Angular projects using the following Angular CLI commands

ng new multi-filters-angular


The following prompts will be asked to select, choose the following in the below screenshots


After the Angular project is created the below screenshot will be displayed



Step 2: Create an Angular component to implement the filter.

  • Create a new angular component to develop a user interface to implement angular multiple filters.

  • Using the following command creates an angular component

cd multi-filters-angular ng generate component product-page (or) ng g c product-page




Step 3: Create a table view based on a sample JSON list.

  • Create a user interface with sample JSON data, it might be a simple table-based view with filters UI at the left side of the page.

  • A sample JSON data is linked in the following below Github link:

link

  • Here is a sample structure of the JSON Data to create UI and for implementing multiple filters logics.


[ { "book_name": "The Great Gatsby", "author": "F. Scott Fitzgerald", "price": 2, "published_date": "2023-03-01", "availability": "not-available" }, { "book_name": "To Kill a Mockingbird", "author": "Harper Lee", "price": 2, "published_date": "2023-03-02", "availability": "not-available" }, { "book_name": "Pride and Prejudice", "author": "Jane Austen", "price": 2, "published_date": "2023-03-03", "availability": "available" }, ]


Step 4: Write logic to implement Multiple filters.

 

The working implementation of the multiple filters logic.

1. select a filter, for example, a date filter.

2. Date range start date ( 01-03-2023 ) and end date ( 09-03-2023 ).

3. After the start and end dates are selected a function (applyDateFilter) is called to implement the date filter.

applyDateFilter() { if (this.startDate !== "" && this.endDate !== "") { this.secondaryFilter.forEach((filterItem: any, index: any) => { if (filterItem.filterType == "date") { this.secondaryFilter.splice(index, 1); } }); this.secondaryFilter.push({ "filterType": "date", "startDate": this.startDate, "endDate": this.endDate, }) this.mainFilterArray.next(this.secondaryFilter); } }

4. In the above function, both the start and end are empty and are validated before applying the filter condition.

5. Two empty arrays are created to store and maintain the filter conditions in JSON format, an example array is given below to create an imagination to understand the logic.

[ { "filterType": "date", "startDate": this.startDate, "endDate": this.endDate, }, { "filterType": "inStock", }, { "filterType": "outOfStock", }, ]

6. The filter conditions are stored in two separate arrays. secondaryFilter is a normal and mainFilterArray is Rxjs Behavior Subject Array.

7. Initially when the filter conditions are applied the values are first stored in a normal array ( secondaryFilter ). Then the normal Array value applied is to the Rxjs Behavior Subject Array (mainFilterArray). A sample code is given below to explain this.

To remove duplicate filter conditions from the array when a condition already exists it will be removed and new filter conditions will be pushed to the array. The below code performs the duplicate removable task.

this.secondaryFilter.forEach((filterItem: any, index: any) => { if (filterItem.filterType == "date") { this.secondaryFilter.splice(index, 1); } });

After duplicates were removed. The filter condition is first added to the secondaryFilter. Then the secondaryFilter array is assigned to the Rxjs Behavior Subject Array (mainFilterArray).

this.secondaryFilter.push({ "filterType": "date", "startDate": this.startDate, "endDate": this.endDate, })

When the filter condition is applied to secondaryFilter. Then the mainFilterArray Array is updated with the new secondaryFilter array.

this.mainFilterArray.next(this.secondaryFilter);

Step 5: Rxjs BehaviorSubject functionality to add reactive filter conditions.

In simple terms when the value of the Rxjs Behavior Subject Array is updated it will call a function automatically so we can perform tasks to respond to the change in filter conditions.

Initializing the Rxjs Behavior Subject Array.

import { BehaviorSubject } from 'rxjs'; // after export class ProductPageComponent implements OnInit mainFilterArray: BehaviorSubject<any> = new BehaviorSubject([]);

 

Listen to the Rxjs Behavior Subject Array for any changes in values. If the value is updated a function will be called.

  • In the below code, when the length of secondary filter array is less than or equal to zero which means filter conditions are not applied. In this scenario, the original data is displayed in the UI. But when the length is greater than zero only filtered data is displayed.

  • When the mainFilterArray value is updated applyFilterConditions function is called to apply filter conditions.

handleChangesInMainFilter() { this.mainFilterArray.subscribe((res) => { if (this.secondaryFilter.length <= 0) { this.filteredData = this.unfilteredData; } else { this.applyFilterConditions(); } }) }

The below code is executed when the applyFilterConditions function is called. In the applyFilterConditions function the logic for filtering JSON data based on the filter conditions stored on the secondary filter array

applyFilterConditions() { this.queriedData = []; this.secondaryFilter.forEach((conditionItem: any) => { if (conditionItem.filterType == "date") { let tempJsonData = this.getSourceJsonData(); console.log("Date Filter source data: ", tempJsonData.length) this.queriedData = []; let startDateFormatted = new Date(conditionItem.startDate); let endDateFormatted = new Date(conditionItem.endDate); tempJsonData.forEach((jsonItem: any) => { let existingDate = new Date(jsonItem.published_date); if ((existingDate >= startDateFormatted) && (existingDate <= endDateFormatted)) { this.queriedData.push(jsonItem); } }); } }); this.filteredData = []; this.filteredData = this.queriedData; }

Step 6: Add new filter condition.

So far we have seen how to implement a filter condition and manipulate data dynamically basic on the applied filter conditions. Now we are going to see how to add new In stock availability filter condition.

  • When the user click on the show in stocks check box the following function wiil be called and the filter condition is pushed to the secondaryFilter and mainFilterArray arrays.





showInStockItems(event: any) { if (event.target.checked === true) { this.secondaryFilter.push({ "filterType": "inStock", }); } else { this.secondaryFilter.forEach((filterItem: any, index: any) => { if (filterItem.filterType == "inStock") { this.secondaryFilter.splice(index, 1); } }); } this.mainFilterArray.next(this.secondaryFilter); }

After when the filter condition is applied the JSON data is filtered according to the condition here is scrrenshot below after applying only “in stocks” filter condition.



Step 7: Remove a filter condition.

  • When you click on the close icon on the applied filtered bubble a function “removeFilterCondition” is called to remove the filter condition from the secondaryFilter array.

  • The below code is the removeFilterCondition function.

removeFilterCondition(filterType: any, index: any){ this.secondaryFilter.splice(index, 1); this.mainFilterArray.next(this.secondaryFilter); if(filterType == "date"){ this.startDate = ""; this.endDate = ""; } else if(filterType == "inStock"){ } }
  • The Rxjs Behavior Subject Array (mainFilterArray) array is updated with the new secondaryFilter array value to implement changes in the filter condition.



Conclusion :

Using the function of the Behavior Subject from Rxjs Library. We can now create a dynamic multiple filter condition to apply on any amount of data without the use of the backend all logical processes are done in the front end side. Which reduces the traffic load to the backend server.

It also improves user experience since the filtering logic is performed on the client side we don't need to wait for API call response.

we had built a sample angular application to demonstrate the multiple filter functionality. The project code is available in GitHub for your reference use the GitHub link below for any queries.



















Comments