Angular Data GridColumn filter

Filter data by values or by a set of conditions, using Handsontable's intuitive user interface or flexible API.

Overview

Filtering lets you quickly find the information that you're looking for, based on specific criteria. This makes data analysis easier and faster, especially with large data sets.

Handsontable's built-in filtering interface resembles Excel's, so it's intuitive even to non-technical users. And if you want to implement your own interface, you can easily filter data programmatically, using Handsontable's API.

You can filter data by value, or use the built-in conditions, which are different for each of the available column types.

Filtering demo

Click on one of the column menu buttons (▼) and play around with filtering by selecting values or conditions-based criteria.

After filtering, the column readjusts its width to the longest value displayed on screen. To disable this behavior, set fixed column widths.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example1',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Enable filtering

To enable the filtering interface for all columns, you need to do two things:

  1. Set the filters option to true.
  2. Enable the interface by setting the dropdownMenu option to true.

Enabling the filters option without the interface can be useful if you plan to create your own custom interface for filtering by using the API.

const configurationOptions = {
  // enable filtering
  filters: true,
  // enable the column menu
  dropdownMenu: true,
};
<hot-table [settings]="configurationOptions"></hot-table>

By default, the column menu presents the filtering interface along with other default items such as Insert column left. To display only the filtering interface, pass an array of filter items in the configuration.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example2',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu, but display only the filter menu items
    dropdownMenu: ['filter_by_condition', 'filter_by_value', 'filter_action_bar'],
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Enable filtering for individual columns

You have control over which columns are filterable and for which columns the column menu is enabled. In the following demo, only the Brand column is filterable, while the other columns are not. However, the Model column still has the column menu available in case you want to have some useful items in the menu such as Clear column.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example3',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering for all columns
    filters: true,
    // enable the column menu for all columns
    // but display only the 'Filter by value' list and the 'OK' and 'Cancel' buttons
    dropdownMenu: {
      items: {
        filter_by_value: {
          // hide the 'Filter by value' list from all columns but the first one
          hidden() {
            // @ts-ignore
            return this.getSelectedRangeLast().to.col > 0;
          },
        },
        filter_action_bar: {
          // hide the 'OK' and 'Cancel' buttons from all columns but the first one
          hidden() {
            // @ts-ignore
            return this.getSelectedRangeLast().to.col > 0;
          },
        },
        clear_column: {
          // hide the 'Clear column' menu item from the first column
          hidden() {
            // @ts-ignore
            return this.getSelectedRangeLast().to.col < 1;
          },
        },
      },
    },
    // `afterGetColHeader()` is a Handsontable hook
    // it's fired after Handsontable appends information about a column header to the table header
    afterGetColHeader(col, TH) {
      // remove the column menu button from the 'Brand', 'Price', and 'Date' columns
      if (col > 1) {
        const button = TH.querySelector('.changeType');

        if (!button) {
          return;
        }

        // @ts-ignore
        button.parentElement.removeChild(button);
      }
    },
    height: 'auto',
    // @ts-ignore
    example: 'exampleEnableFilterInColumns',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Filter different types of data

With its built-in cell types, Handsontable makes it easy to handle common data types like text, numbers, and dates by providing numerous configuration options. In addition, the filtering feature is designed to understand the underlying data and provides an adaptive interface that is tailored to each data type.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example4',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      model: 'Racing Socks',
      size: 'S',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
      color: 'Black',
    },
    {
      model: 'HL Mountain Shirt',
      size: 'XS',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
      color: 'White',
    },
    {
      model: 'Cycling Cap',
      size: 'L',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
      color: 'Green',
    },
    {
      model: 'Ski Jacket',
      size: 'M',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
      color: 'Blue',
    },
    {
      model: 'HL Goggles',
      size: 'XL',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
      color: 'Black',
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Model',
        // set the type of the 'Model' column
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        // set the type of the 'Price' column
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Sold on',
        // set the type of the 'Date' column
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        // set the type of the 'Time' column
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        // set the type of the 'In stock' column
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
      {
        title: 'Size',
        // set the type of the 'Size' column
        type: 'dropdown',
        data: 'size',
        source: ['XS', 'S', 'M', 'L', 'XL'],
        className: 'htCenter',
      },
      {
        title: 'Color',
        // set the type of the 'Size' column
        type: 'autocomplete',
        data: 'color',
        source: ['White', 'Black', 'Yellow', 'Blue', 'Green'],
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    height: 175,
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

The following table contains all available filter operators for each built-in data type.

Cell type Available filter operators
All cell types Default operators:

None
Is empty
Is not empty
Is equal to
Is not equal to
text
time
checkbox
dropdown
autocomplete
password
Default operators plus:

Begins with
Ends with
Contains
Does not contain
numeric Default operators plus:

Greater than
Greater than or equal to
Less than
Less than or equal to
Is between
Is not between
date Default operators plus:

Before
After
Is between
Tomorrow
Today
Yesterday

Filter data on initialization

You can filter data on Handsontable's initialization. This lets you apply pre-defined filters every time you launch your grid.

To do this, you can use Handsontable's afterInit() hook, along with the API provided by the Filters plugin. For instance, the demo below demonstrates how you can start with a pre-applied filter to display only items priced less than $200.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example5',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    // `afterInit()` is a Handsontable hook: it's fired after the Handsontable instance is initiated
    afterInit() {
      const handsontableInstance = this;
      // get the `Filters` plugin, so you can use its API
      // @ts-ignore
      const filters = handsontableInstance.getPlugin('filters');

      // filter data by the 'Price' column (column at index 2)
      // to display only items that are less than ('lt') $200
      filters.addCondition(2, 'lt', [200]);
      filters.filter();
    },
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

External quick filter

Handsontable's quick filter feature lets you search for a particular phrase in a specific column. To accomplish this, use methods filters.addCondition() and filters.filter().

/* file: app.component.ts */
import {Component, OnInit, ViewChild} from '@angular/core';
import { GridSettings, HotTableComponent } from "@handsontable/angular-wrapper";
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-example6',
  template: `
    <div class="example-controls-container">
      <div class="controlsQuickFilter">
        <label for="columns" class="selectColumn">Select a column:
          <select [formControl]="columnControl" id="columns">
            <option *ngFor="let option of columnOptions" [value]="option.value">
              {{option.label}}
            </option>
          </select>
        </label>
      </div>
      <div class="controlsQuickFilter">
        <input id="filterField" [formControl]="fieldControl" type="text" placeholder="Filter"/>
      </div>
    </div>

    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  styles: `
    .controlsQuickFilter {
      margin: 0;
      padding: 0;
    }

    #filterField {
      margin-top: 20px;
    }
  `,
  standalone: false
})
export class AppComponent implements OnInit {
  @ViewChild(HotTableComponent, {static: false}) hotTable!: HotTableComponent;

  fieldControl = new FormControl('');
  columnControl = new FormControl('0');

  columnOptions: Array<{value: string; label: string}> = [
    { value: '0', label: 'Brand' },
    { value: '1', label: 'Model' },
    { value: '2', label: 'Price' },
    { value: '3', label: 'Date' },
    { value: '4', label: 'Time' },
    { value: '5', label: 'In stock' },
  ];

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: '11/10/2023',
      sellTime: '01:23',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: '03/05/2023',
      sellTime: '11:27',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: '27/03/2023',
      sellTime: '03:17',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: '28/08/2023',
      sellTime: '08:01',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: '02/10/2023',
      sellTime: '13:23',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    colHeaders: true,
    height: 'auto',
    filters: true,
    className: 'exampleQuickFilter',
    autoWrapRow: true,
    autoWrapCol: true,
  };

  ngOnInit() {
    this.fieldControl.valueChanges.subscribe((fieldValue: string) => {
      const filters = this.hotTable.hotInstance!.getPlugin('filters');
      const columnValue = +this.columnControl.value!;

      filters.removeConditions(columnValue);
      filters.addCondition(columnValue, 'contains', [fieldValue]);
      filters.filter();
      this.hotTable.hotInstance!.render();
    })
  }
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule, ReactiveFormsModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Customize the filter button

The default button that opens the column menu can be styled with CSS by modifying button.changeType variables and its ::before pseudoclass that contains svg mask-image displaying an arrow down icon.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example7',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  styles: `
    :host ::ng-deep {
      .handsontable.customFilterButtonExample1 .changeType {
        --ht-icon-button-background-color: #e2e2e263;
        --ht-icon-button-border-radius: 100%;
      }

      .handsontable.customFilterButtonExample1 .changeType::before {
        -webkit-mask-image: url("data:image/svg+xml,%3Csvg width=%2716%27 height=%2716%27 viewBox=%270 0 16 16%27 fill=%27none%27 xmlns=%27http://www.w3.org/2000/svg%27%3E%3Cpath d=%27M6.83337 7.99984C6.83337 8.30926 6.95629 8.606 7.17508 8.8248C7.39388 9.04359 7.69062 9.1665 8.00004 9.1665C8.30946 9.1665 8.60621 9.04359 8.825 8.8248C9.04379 8.606 9.16671 8.30926 9.16671 7.99984C9.16671 7.69042 9.04379 7.39367 8.825 7.17488C8.60621 6.95609 8.30946 6.83317 8.00004 6.83317C7.69062 6.83317 7.39388 6.95609 7.17508 7.17488C6.95629 7.39367 6.83337 7.69042 6.83337 7.99984Z%27 fill=%27%23222222%27/%3E%3Cpath d=%27M6.83337 12.4165C6.83337 12.7259 6.95629 13.0227 7.17508 13.2415C7.39388 13.4603 7.69062 13.5832 8.00004 13.5832C8.30946 13.5832 8.60621 13.4603 8.825 13.2415C9.04379 13.0227 9.16671 12.7259 9.16671 12.4165C9.16671 12.1071 9.04379 11.8103 8.825 11.5915C8.60621 11.3728 8.30946 11.2498 8.00004 11.2498C7.69062 11.2498 7.39388 11.3728 7.17508 11.5915C6.95629 11.8103 6.83337 12.1071 6.83337 12.4165Z%27 fill=%27%23222222%27/%3E%3Cpath d=%27M6.83337 3.58317C6.83337 3.89259 6.95629 4.18934 7.17508 4.40813C7.39388 4.62692 7.69062 4.74984 8.00004 4.74984C8.30946 4.74984 8.60621 4.62692 8.825 4.40813C9.04379 4.18934 9.16671 3.89259 9.16671 3.58317C9.16671 3.27375 9.04379 2.97701 8.825 2.75821C8.60621 2.53942 8.30946 2.4165 8.00004 2.4165C7.69062 2.4165 7.39388 2.53942 7.17508 2.75821C6.95629 2.97701 6.83337 3.27375 6.83337 3.58317Z%27 fill=%27currentColor%27/%3E%3C/svg%3E");
      }
    }
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    // to differentiate this example's CSS from other examples on this page
    className: 'customFilterButtonExample1',
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

The column menu button is always visible, but if you want it to appear only when the mouse cursor is over the header, apply additional styling to th .relative:hover .changeType.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example8',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  styles: `
    :host ::ng-deep {
      /* hide the column menu button by default */
      .customFilterButtonExample2 .changeType {
        visibility: hidden;
      }

      /* show the column menu button on hover */
      .customFilterButtonExample2 th .relative:hover .changeType {
        visibility: visible;
      }
    }
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    // to differentiate this example's CSS from other examples on this page
    className: 'customFilterButtonExample2',
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Change the width of the filter menu

If the text data in your columns is too long to fit in the filters container, you can adjust the column menu's width for better user experience. You can achieve this with by styling .htDropdownMenu table.htCore.

.handsontable .htDropdownMenu table.htCore {
  width: 300px !important;
}

Exclude rows from filtering

You can exclude any number of top or bottom rows from filtering.

In the following demo, the first and the last row are frozen, and filtering doesn't affect them.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example9',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: 11,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: 0,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: 1,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '13:23 AM',
      inStock: 3,
    },
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: 5,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: 22,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: 13,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: 0,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '13:23 AM',
      inStock: 14,
    },
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: 16,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: 18,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: 3,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: 0,
    },
    {
      brand: 'Vinte',
      model: 'ML Road Frame-W',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: 2,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
        className: 'htRight',
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'numeric',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    height: 200,
    colWidths: [120, 150, 120, 140, 120, 120],
    fixedRowsTop: 1,
    fixedRowsBottom: 1,
    minSpareRows: 1,
    colHeaders: true,
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    afterFilter() {
      // @ts-ignore
      const filtersPlugin = this.getPlugin('filters');
      const filtersRowsMap = filtersPlugin.filtersRowsMap;

      filtersRowsMap.setValueAtIndex(0, false);
      filtersRowsMap.setValueAtIndex(
        filtersRowsMap.indexedValues.length - 1,
        false
      );
    },
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Server-side filtering

You can decide to use Handsontable as an intuitive filtering interface, but perform the actual filtering on the server.

To help you with that, Handsontable's beforeFilter() hook allows you to:

  • Gather information about the filters that the user wants to apply, to send it to the server.
  • Disable filtering on the front end, so it doesn't interfere with filtering on the server.

In the following demo, click on one of the column menu buttons (▼) and play around with filtering by selecting values or conditions-based criteria. After you click OK, the ▼ button turns green to indicate filtering, but the data is not filtered. Instead, the information about the specified filters is logged to the console.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from "@handsontable/angular-wrapper";

@Component({
  selector: 'app-example10',
  template: `
    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    height: 'auto',
    // `beforeFilter()` is a Handsontable hook
    // it's fired after Handsontable gathers information about the filters, but before the filters are applied
    beforeFilter(conditionsStack) {
      // gather information about the filters
      console.log(`The amount of filters: ${conditionsStack.length}`);
      console.log(`The last changed column index: ${conditionsStack[0].column}`);
      console.log(
        `The amount of filters added to this column: ${conditionsStack[0].conditions.length}`
      );
      // the list of filter conditions
      console.log(conditionsStack[0].conditions);

      // return `false` to disable filtering on the client side
      return false;
    },
    autoWrapRow: true,
    autoWrapCol: true,
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Control filtering programmatically

You can control filtering at the grid's runtime by using Handsontable's hooks and API methods. This allows you to enable or disable filtering based on specific conditions. For example, you may create a user interface outside of the grid to manage Handsontable's filtering behavior.

Enable or disable filtering programmatically

To enable or disable filtering programmatically, use the updateSettings() method.

@ViewChild(HotTableComponent, {static: false}) hotTable!: HotTableComponent;

this.hotTable.hotInstance!.updateSettings({
  // enable filtering
  filters: true,
  // enable the column menu
  dropdownMenu: true,
});

this.hotTable.hotInstance!.updateSettings({
  // disable filtering
  filters: false,
});

You can also enable or disable filtering for specific columns. For example, to enable filtering only for the first column:

@ViewChild(HotTableComponent, {static: false}) hotTable!: HotTableComponent;

this.hotTable.hotInstance!.updateSettings({
  // enable filtering, for all columns
  filters: true,
  // enable the column menu, for all columns
  // but display only the 'Filter by value' list and the 'OK' and 'Cancel' buttons
  dropdownMenu: {
    items: {
      filter_by_value: {
        // hide the 'Filter by value' list from all columns but the first one
        hidden() {
          return this.getSelectedRangeLast().to.col > 0;
        },
      },
      filter_action_bar: {
        // hide the 'OK' and 'Cancel' buttons from all columns but the first one
        hidden() {
          return this.getSelectedRangeLast().to.col > 0;
        },
      },
    },
  },
});

Filter data programmatically

To filter data programmatically, use the Filters plugin's API. Remember to enable filtering first.

Mind that before you apply new filter conditions, you need to clear the previous ones with filters.clearConditions().

/* file: app.component.ts */
import { Component, ViewChild } from '@angular/core';
import { GridSettings, HotTableComponent } from '@handsontable/angular-wrapper';
import { Filters } from 'handsontable/plugins';

@Component({
  selector: 'app-example11',
  template: `
    <div class="example-controls-container">
      <div class="controls">
        <button (click)="filterBelow200()">Show items < $200</button>
        <button (click)="filterAbove200()">Show items > $200</button>
        <button (click)="clearAllFilters()">Clear filters</button>
      </div>
    </div>

    <hot-table
      [settings]="hotSettings!" [data]="hotData">
    </hot-table>
  `,
  standalone: false
})
export class AppComponent {
  @ViewChild(HotTableComponent, {static: false}) hotTable!: HotTableComponent;

  readonly hotData = [
    {
      brand: 'Jetpulse',
      model: 'Racing Socks',
      price: 30,
      sellDate: 'Oct 11, 2023',
      sellTime: '01:23 AM',
      inStock: false,
    },
    {
      brand: 'Gigabox',
      model: 'HL Mountain Frame',
      price: 1890.9,
      sellDate: 'May 3, 2023',
      sellTime: '11:27 AM',
      inStock: false,
    },
    {
      brand: 'Camido',
      model: 'Cycling Cap',
      price: 130.1,
      sellDate: 'Mar 27, 2023',
      sellTime: '03:17 AM',
      inStock: true,
    },
    {
      brand: 'Chatterpoint',
      model: 'Road Tire Tube',
      price: 59,
      sellDate: 'Aug 28, 2023',
      sellTime: '08:01 AM',
      inStock: true,
    },
    {
      brand: 'Eidel',
      model: 'HL Road Tire',
      price: 279.99,
      sellDate: 'Oct 2, 2023',
      sellTime: '01:23 AM',
      inStock: true,
    },
  ];

  readonly hotSettings: GridSettings = {
    columns: [
      {
        title: 'Brand',
        type: 'text',
        data: 'brand',
      },
      {
        title: 'Model',
        type: 'text',
        data: 'model',
      },
      {
        title: 'Price',
        type: 'numeric',
        data: 'price',
        numericFormat: {
          pattern: '$ 0,0.00',
          culture: 'en-US',
        },
      },
      {
        title: 'Date',
        type: 'date',
        data: 'sellDate',
        dateFormat: 'MMM D, YYYY',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'Time',
        type: 'time',
        data: 'sellTime',
        timeFormat: 'hh:mm A',
        correctFormat: true,
        className: 'htRight',
      },
      {
        title: 'In stock',
        type: 'checkbox',
        data: 'inStock',
        className: 'htCenter',
      },
    ],
    // enable filtering
    filters: true,
    // enable the column menu
    dropdownMenu: true,
    height: 'auto',
    autoWrapRow: true,
    autoWrapCol: true,
  };


  // get the `Filters` plugin, so you can use its API
  getFiltersPlugin(): Filters {
    return this.hotTable.hotInstance!.getPlugin('filters');
  }

  filterBelow200() {
    const filters = this.getFiltersPlugin();

    // clear any existing filters
    filters.clearConditions();
    // filter data by the 'Price' column (column at index 2)
    // to display only items that are less than ('lt') $200
    filters.addCondition(2, 'lt', [200]);
    filters.filter();
  }

  filterAbove200() {
    const filters = this.getFiltersPlugin();

    filters.clearConditions();
    // display only items that are more than ('gt') $200
    filters.addCondition(2, 'gt', [200]);
    filters.filter();
  }

  clearAllFilters() {
    const filters = this.getFiltersPlugin();

    filters.clearConditions();
    filters.filter();
  }
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';

import { AppComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ AppComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Import the filtering module

You can reduce the size of your bundle by importing and registering only the modules that you need.

To use filtering, you need only the following modules:

// import the base module
import Handsontable from 'handsontable/base';

// import Handsontable's CSS
import 'handsontable/styles/handsontable.css';
import 'handsontable/styles/ht-theme-main.css';

// import the filtering plugins
import { registerPlugin, Filters, DropdownMenu } from 'handsontable/plugins';

// register the filtering plugins
registerPlugin(Filters);
registerPlugin(DropdownMenu);

Known limitations

At the moment, filtering comes with the following limitations:

  • There is no easy way to add custom filter operators to the user interface.
  • The list of values that you can filter by is generated automatically and there's no supported way of modifying it.
Windows macOS Action Excel Sheets
Alt+A Option+A Clear all filters

API reference

For the list of options, methods, and Handsontable hooks related to filtering, see the following API reference pages:

Troubleshooting

Didn't find what you need? Try this: