Files
ISA-Frontend/libs/shared/filter
Nino Righi 405bf5b463 Merged PR 1847: fix(shared-filter): add mapFilterInputToRecord util and refactor query mapping
fix(shared-filter): add mapFilterInputToRecord util and refactor query mapping

Introduce mapFilterInputToRecord utility for consistent mapping of filter inputs to query parameter records. Refactor FilterService.query to use this utility for both filter and input groups, ensuring DRY code and improved maintainability.

Add unit tests for the new mapping function and update the mappings index export.

Ref: #5105, #5106, #5143
2025-06-05 17:14:05 +00:00
..

ISA Filter Library

A powerful and flexible filtering library for Angular applications that provides a complete solution for implementing filters, search functionality, and sorting capabilities.

Overview

The ISA Filter Library is designed to help developers quickly implement advanced filtering capabilities in their Angular applications. It provides a set of reusable components, schemas, and services to handle various types of filters, user inputs, and sorting options.

Features

  • Multiple Filter Types: Support for text search, checkboxes, date ranges, and more
  • Flexible Architecture: Easily extendable to support custom filter types
  • Modern Angular Patterns: Built with Angular signals for reactive state management
  • Schema-based Validation: Type-safe filter models with zod schema validation
  • Responsive Design: Mobile-friendly filter UI components
  • Declarative API: Simple and intuitive API for configuring filters
  • Sorting Capabilities: Built-in support for sorting data by various criteria
  • TypeScript Support: Fully typed for excellent developer experience

Installation

The library is part of the ISA Frontend monorepo and can be imported using:

import { ... } from '@isa/shared/filter';

Core Concepts

Filter Service

The FilterService is the central component of the library, responsible for managing filter state and providing methods to update and query filter values.

// Example of using FilterService
export class MyComponent {
  constructor(private filterService: FilterService) {}

  applyFilters() {
    // Apply filters and get the query
    const query = this.filterService.getQuery();
    // Use the query to fetch filtered data
  }

  resetFilters() {
    this.filterService.reset();
  }
}

Filter Types

The library supports several filter input types:

  • Text Filters (InputType.Text): For search queries and text-based filtering
  • Checkbox Filters (InputType.Checkbox): For multi-select options
  • Date Range Filters (InputType.DateRange): For time-based filtering

Query Settings

Filter configurations are defined using the QuerySettings interface, which includes filter groups, input fields, and sort options.

// Example QuerySettings configuration
const settings: QuerySettings = {
  filter: [
    {
      group: 'products',
      label: 'Product Filters',
      input: [
        {
          key: 'category',
          label: 'Category',
          type: InputType.Checkbox,
          options: {
            values: [
              { label: 'Electronics', value: 'electronics' },
              { label: 'Clothing', value: 'clothing' },
            ],
          },
        },
      ],
    },
  ],
  input: [],
  orderBy: [
    { by: 'price', label: 'Price (Low to High)', desc: false },
    { by: 'price', label: 'Price (High to Low)', desc: true },
  ],
};

Components

Filter Menu

The FilterMenuComponent provides a UI for displaying and interacting with filters:

<filter-filter-menu (applied)="onApplyFilters()" (reseted)="onResetFilters()">
</filter-filter-menu>

Order By Toolbar

The OrderByToolbarComponent allows users to sort data based on different criteria:

<filter-order-by-toolbar [commitOnToggle]="true" (toggled)="onSortChanged()">
</filter-order-by-toolbar>

Input Components

The library includes specialized components for different input types:

  • CheckboxInputComponent: For multi-select options
  • DatepickerRangeInputComponent: For date range selection
  • SearchBarInputComponent: For text-based search

Input Renderer

The InputRendererComponent dynamically renders the appropriate input component based on the filter type:

<filter-input-renderer [filterInput]="myFilterInput"></filter-input-renderer>

Usage Examples

Basic Filter Implementation

// Import filter library
import { QuerySettings, InputType, provideFilter } from '@isa/shared/filter';

// Define filter settings
const settings: QuerySettings = {
  filter: [
    {
      group: 'filter',
      label: 'Filters',
      input: [
        {
          key: 'status',
          label: 'Status',
          type: InputType.Checkbox,
          options: {
            values: [
              { label: 'Active', value: 'active' },
              { label: 'Inactive', value: 'inactive' },
            ],
          },
        },
      ],
    },
  ],
  input: [],
  orderBy: [
    { by: 'name', label: 'Name (A-Z)', desc: false },
    { by: 'name', label: 'Name (Z-A)', desc: true },
  ],
};

// Provide filter in component/module
@Component({
  // ...
  providers: [provideFilter(settings)],
})
export class MyFilterComponent {
  // ...
}

Implementing Filter Logic

@Component({
  // ...
})
export class ProductListComponent {
  constructor(private filterService: FilterService) {}

  products = computed(() => {
    const query = this.filterService.getQuery();
    return this.applyFilters(this.allProducts, query);
  });

  private applyFilters(products: Product[], query: Query): Product[] {
    // Implement filtering logic based on query
    return filteredProducts;
  }

  onApplyFilters() {
    // Trigger data refresh or update
  }
}

Schema Validation

The library uses Zod schemas to validate filter configurations and user inputs:

// Example of a filter schema
export const CheckboxFilterInputSchema = CheckboxFilterInputBaseSchema.extend({
  options: z
    .object({
      values: z.array(CheckboxFilterInputOptionSchema).optional(),
      max: z.number().optional(),
    })
    .optional(),
  selected: z.array(z.string()).default([]),
  type: z.literal(InputType.Checkbox),
});

Architecture

The Filter library is organized into several key modules:

Core Module

  • Schemas: Type definitions and validation using Zod
  • Mappings: Functions to transform between API and UI models
  • Service: The FilterService for state management
  • Tokens: Injection tokens for DI configuration

Inputs Module

  • CheckboxInput: Multi-select options component
  • DatepickerRangeInput: Date range selection component
  • SearchBarInput: Text-based search component
  • InputRenderer: Dynamic component renderer

Menus Module

  • FilterMenu: UI for displaying and interacting with filters
  • InputMenu: Specialized component for input configuration

Actions Module

Components for filter operations (apply, reset, etc.)

Order By Module

Components for sorting data based on different criteria

Best Practices

  1. Group Related Filters: Use filter groups to organize related filters together
  2. Provide Clear Labels: Use descriptive labels for filters and options
  3. Use Appropriate Filter Types: Choose the right filter type for the data being filtered
  4. Handle Filter State: Properly manage filter state, especially for URL synchronization
  5. Combine with NgRx: For complex applications, consider using the library with NgRx for state management

Running unit tests

Run nx test shared-filter to execute the unit tests.