Building a Dynamic Filter Service with Angular

Building a Dynamic Filter Service with Angular

Filtering data is a common requirement in many Angular applications. Whether it’s a list of products, users, or any other dataset, providing users with the ability to filter and search through the data can greatly enhance the user experience. In this tutorial, we’ll explore how to create a dynamic filter service in Angular using reactive forms and RxJS.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Creating the FilterService
  4. Implementing the AppComponent
  5. Conclusion

Prerequisites

Before we begin, make sure you have the following installed:

  • Angular CLI
  • Node.js and npm

Creating the FilterService

Our goal is to build a reusable service that handles the filtering logic for any dataset. We’ll use Angular’s reactive forms for managing the filter inputs and RxJS for handling changes. Here’s the implementation of the FilterService:

// filter.service.ts
import { Injectable } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';

@Injectable({
  providedIn: 'root',
})
export class FilterService {
  filtersForm: FormGroup;
  filterValues: { [key: string]: any } = {};

  constructor() {
    this.filtersForm = new FormGroup({});
  }

  applyFilters<T>(items: T[], customFilterFn?: (item: T) => boolean): T[] {
    let filteredItems = [...items];

    for (const key of Object.keys(this.filterValues)) {
      const filterValue = this.filterValues[key].toLowerCase();
      if (filterValue) {
        filteredItems = filteredItems.filter((item) =>
          (item[key] as any).toString().toLowerCase().includes(filterValue)
        );
      }
    }

    if (customFilterFn) {
      filteredItems = filteredItems.filter(customFilterFn);
    }

    return filteredItems;
  }

  addFormControl(controlName: string, defaultValue: any = '') {
    this.filtersForm.addControl(controlName, new FormControl(defaultValue));
    this.filterValues[controlName] = defaultValue;
  }

  setFilterValues(values: { [key: string]: any }) {
    this.filterValues = values;
    this.filtersForm.setValue(values);
  }

  clearFilters() {
    this.filterValues = {};
    this.filtersForm.reset();
  }
}

Implementing the AppComponent

Let’s integrate the FilterService into an Angular component. Here’s how you can create a filtering interface for a list of items and provide the option to filter based on the “Search” button click:

// app.component.ts
import { Component } from '@angular/core';
import { FilterService } from './filter.service';

@Component({
  selector: 'my-app',
  template: `
    <!-- Filter form -->
    <form [formGroup]="filterService.filtersForm">
      <input type="text" formControlName="name" placeholder="Filter by Name">
      <input type="text" formControlName="category" placeholder="Filter by Category">
     
      <button (click)="search()">Search</button>
      <button (click)="clearFilters()">Clear Filters</button>
    </form>
    
    <!-- Display filtered items -->
    <ul>
      <li *ngFor="let item of filteredItems">{{ item.name }} ({{ item.category }})</li>
    </ul>
  `,
})
export class AppComponent {
 items = [
    { name: 'Apple', category: 'Fruit' },
    { name: 'Banana', category: 'Fruit' },
    { name: 'Carrot', category: 'Vegetable' },
    { name: 'Kiwi', category: 'Fruit' },
    { name: 'Lemon', category: 'Vegetable' },
  ];

  filteredItems: any[];

  constructor(public filterService: FilterService) {
    this.filteredItems = this.items;
    this.filterService.addFormControl('name');
    this.filterService.addFormControl('category');
  }

  customFilter(item: any): boolean {
    // Implement your custom filtering logic here
    return true; // Placeholder logic, you can change this
  }

  clearFilters() {
    this.filterService.clearFilters();
    this.filteredItems = this.items; // Reset filtered items to all items
  }

  search() {
    this.updateFilteredItems();
  }

  updateFilteredItems() {
    this.filteredItems = this.filterService.applyFilters(
      this.items,
      this.customFilter
    );
  }
}

Conclusion

In this tutorial, we’ve built a dynamic filter service in Angular using reactive forms and the FilterService class. By utilizing the filterValues property, you can control the behavior of the filters and apply them when needed. This approach allows you to create a user-friendly and efficient filtering mechanism for various datasets in your Angular applications.

Feel free to customize the filtering logic and UI elements to match the requirements of your application. Whether you choose to filter on value changes or on button click, this foundation allows you to create advanced filtering experiences while keeping your code modular and maintainable.

That’s it! You now have a powerful and reusable filtering mechanism for your Angular applications.