Skip to content

a prototype project for demonstrating an Angular customizable and reusable filter component that seamlessly integrates with various tables.

License

Notifications You must be signed in to change notification settings

liemwellys/reusable-filter-form-array

Repository files navigation

Reusable Filter Template using Angular Form Array

This project is demo for reusable filter template component used to filter a table record that allows users to build dynamic filters with various input types. It leverages Angular's reactive forms and Form Arrays to create a flexible and adaptable solution.

Developed using Angular and Angular Material v14.

Features

  • Multiple Input Types: Supports autocomplete, plain string, dropdown selector, and time inputs for diverse filtering needs.
  • Reusable Component: Can be used across different parts of your application to create consistent filtering experiences.
  • Configurable: Define filter options through a configuration object passed to the component.
  • JSON Output: Generates a JSON object containing key-value pairs representing the selected filter criteria. This object is emitted to the parent component and can be appended to query parameters for data retrieval.

Running the program

  1. Clone the repository
git clone https://github.com/liemwellys/reusable-filter-form-array.git
  1. Install required packages
npm install --no-save

Filter Usage & Configuration

  1. Prepare a filter config & a timestamp filter config. In this demo, the sample config is available on this file and imported to ParentComponent.
// filter config
export const memberfilters: Filter[] = [
  {
    type: 'autoComplete',
    name: 'name',
    label: 'member.name',
    isSet: false,
    // autoCompleteUrl: '/path/to/data/retrieval/on/configured/API/provider'
  },
  {
    type: 'string',
    name: 'address',
    label: 'member.address',
    isSet: false,
  },
  {
    type: 'autoComplete',
    name: 'district',
    label: 'member.district',
    isSet: false,
    // autoCompleteUrl: '/path/to/data/retrieval/on/configured/API/provider'
  },
  {
    type: 'selection',
    name: 'city',
    label: 'member.city',
    options: [
      { name: 'London', value: 'London' },
      { name: 'Manchester', value: 'Manchester' },
      { name: 'Birmingham', value: 'Birmingham' },
      { name: 'Leeds', value: 'Leeds' },
      { name: 'Liverpool', value: 'Liverpool' },
      { name: 'Newcastle', value: 'Newcastle' },
      { name: 'Nottingham', value: 'Nottingham' },
    ],
    isSet: false,
  },
  {
    type: 'time',
    name: 'createdAt',
    label: 'member.createdAt',
    options: [
      { name: 'filterMenu.before', value: 'max' },
      { name: 'filterMenu.after', value: 'min' },
      { name: 'filterMenu.at', value: 'minMax' },
      { name: 'filterMenu.between', value: 'between' },
    ],
    isSet: false,
  },
];

// timestamp filter config
export const memberTimeStampFilters = ['createdAt'];
  1. Add reusable filter component into a parent component template & bind memberFilters & memberTimeStampFilters on each corresponding property binding.
<app-reusable-filter
  [filters]="memberFilters"
  [timeStampFilters]="memberTimeStampFilters"
></app-reusable-filter>
  • Optional: Bind a table name to retrieve preset mock data. Since the current project does not have an API provider, the mock table name is set to member and implementing mock data retrieval using _filterAutoCompleteOptionsMockAPI. The function for data retrieval from the API provider has already been set up in _filterAutoCompleteOptionsAPI and needs to be configured based on your project setup.
<app-reusable-filter ... [tableName]="'member'"></app-reusable-filter>
  1. Add a variable & method in parent component for store the emitted filter object from reusable filter component.
export class ParentComponent implements OnInit {
  ...

  // variable for store emitted filter object
  filterObject: unknown;

  /**
   * a method to receive & store filter object
   * optional: send GET request to configured API provider
   * once filter received on parent component
   */
  receiveFilter(filter: unknown): void {
    this.filterObject = filter;
  }
}
  1. Bind receiveFilter() method with applyFilter event.
<app-reusable-filter ... (applyFilter)="receiveFilter($event)"></app-reusable-filter>

Sample Output

The following example is a sample output when the user fills out all of the defined available filter fields. It demonstrates how the filter criteria are represented in a JSON object. In this case, the user has entered the following filter values:

  • Name: John Smith
  • Address: No. 18, Lane 71
  • District: Southwark
  • City: Nottingham
  • Created before: 2024/06/27 00:00

The JSON object generated from these filter values is as follows:

{
  "name": "John Smith",
  "address": "No. 18, Lane 71",
  "district": "Southwark",
  "city": "Nottingham",
  "maxCreatedAt": 1719417600
}

For the time filter, the filter key's name will be the time constraint selection followed by the filter name. In this case, since the user selected the "Before" time constraint and the filter name is "createdAt", the key's name will be maxCreatedAt.

The other possible keys based on the user's selection are as follows:

  • After: minCreatedAt
{
  "minCreatedAt": 1719417600
}
  • At: minCreatedAt and maxCreatedAt
{
  "minCreatedAt": 1719417600,
  "maxCreatedAt": 1719417600
}
  • Between: minCreatedAt and maxCreatedAt
{
  "minCreatedAt": 1719417600,
  "maxCreatedAt": 1719489367
}

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

a prototype project for demonstrating an Angular customizable and reusable filter component that seamlessly integrates with various tables.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published