Filter menu in Angular Gantt component

13 Oct 202524 minutes to read

The Syncfusion® Angular Gantt component offers a filter menu for each column, enabling you to filter data based on column type and supported operators such as equal, contains, greaterthan, etc. To enable this feature, set allowFiltering to true and configure filterSettings.type as Menu.

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { GanttModule, FilterService } from '@syncfusion/ej2-angular-gantt';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GanttModule],
  providers: [FilterService],
  encapsulation: ViewEncapsulation.None,
  template: `
    <ejs-gantt height="370px" [allowFiltering]="true" [dataSource]="data" [taskFields]="taskSettings" [columns]="columns" [splitterSettings]="splitterSettings" [filterSettings]="filterSettings">
    </ejs-gantt>
  `
})
export class AppComponent implements OnInit {
  public data: object[] = [];
  public taskSettings: object = {};
  public columns: object[] = [];
  public splitterSettings: object = {};
  public filterSettings: object = {};

  ngOnInit(): void {
    this.data = [
      { TaskId: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskId: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentId: 1, Progress: 50 },
      { TaskId: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentId: 1, Progress: 50 },
      { TaskId: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentId: 1, Progress: 50 },
      { TaskId: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskId: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentId: 5, Progress: 50 },
      { TaskId: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentId: 5, Progress: 50 },
      { TaskId: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentId: 5, Progress: 50 }
    ];
    this.taskSettings = {
      id: 'TaskId',
      name: 'TaskName',
      startDate: 'StartDate',
      endDate: 'EndDate',
      duration: 'Duration',
      progress: 'Progress',
      parentID: 'ParentId'
    };
    this.columns = [
      { field: 'TaskId', headerText: 'Task ID', textAlign: 'Left', width: '100' },
      { field: 'TaskName', headerText: 'Task Name', width: '250' },
      { field: 'StartDate', headerText: 'Start Date', width: '150' },
      { field: 'Duration', headerText: 'Duration', width: '150' },
      { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    this.splitterSettings = {
      columnIndex: 3
    };
    this.filterSettings = {
      type: 'Menu'
    };
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

To prevent the filter menu from rendering for a specific column, set columns.allowFiltering to false.

Custom component in filter menu

You can customize the filter menu in the Syncfusion® Angular Gantt component using the column.filter.ui property. This allows you to replace the default filter controls with custom components such as dropdowns or textboxes for specific columns. By default, the Gantt uses AutoComplete for string columns, NumericTextBox for number columns, DatePicker for date columns, DropDownList for boolean columns, and DateTimePicker for datetime columns.

The column.filter.ui property supports three essential functions:

  1. create- Initializes and renders the custom filter component inside the filter menu.
  2. write- Populates the component with the current filter value and attaches any necessary event handlers.
  3. read - Retrieves the selected value from the component and applies the filter to the column.
import { Component, OnInit, ViewChild, ViewEncapsulation} from '@angular/core';
import { GanttModule, GanttComponent, FilterService } from '@syncfusion/ej2-angular-gantt';
import { DropDownListComponent, DropDownList, DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns';
import { createElement } from '@syncfusion/ej2-base';
import { DataManager } from '@syncfusion/ej2-data';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GanttModule, DropDownListAllModule],
  providers: [FilterService],
  encapsulation: ViewEncapsulation.None,
  template: `
    <ejs-gantt #gantt height="370px" [allowFiltering]="true" [dataSource]="data" [taskFields]="taskSettings" [splitterSettings]="splitterSettings" [columns]="columns" [filterSettings]="filterSettings">
    </ejs-gantt>`
})

export class AppComponent implements OnInit {
  @ViewChild('gantt', { static: true }) public gantt!: GanttComponent;
  @ViewChild('fieldDropdown') public fieldDropdown!: DropDownListComponent;
  @ViewChild('typeDropdown') public typeDropdown!: DropDownListComponent;
  public data: Task[] = [];
  public taskSettings = {};
  public splitterSettings = {};
  public filterSettings = {};
  public columns: object[] = [];
  public dropInstance!: DropDownList;
  public filter!: FilterUI;

  ngOnInit(): void {
    this.data = [
      { TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 }
    ];
    this.taskSettings = {
      id: 'TaskID',
      name: 'TaskName',
      startDate: 'StartDate',
      duration: 'Duration',
      progress: 'Progress',
      parentID: 'ParentID'
    };
    this.filter = {
      ui: {
       // Creates the custom dropdown filter UI for the column.
        create: (args: { target: Element; column: object }) => {
          const flValInput: HTMLElement = createElement('input', { className: 'flm-input' });
          args.target.appendChild(flValInput);
          this.dropInstance = new DropDownList({
            dataSource: new DataManager(this.data),
            fields: { text: 'TaskName', value: 'TaskName' },
            placeholder: 'Select a value',
            popupHeight: '200px'
          });
          this.dropInstance.appendTo(flValInput);
        },
        // Writes the selected filter value into the dropdown.
        write: (args: { column: object; target: Element; filteredValue: string }) => {
          this.dropInstance.value = args.filteredValue;
        },

        // Reads the selected value from the dropdown and applies the filter.
        read: (args: { target: Element; column: Column; operator: string; fltrObj: any }) => {
          args.fltrObj.filterByColumn(args.column.field, args.operator, this.dropInstance.value);
        }
      }
    };
    this.columns = [
      { field: 'TaskID', headerText: 'Task ID', width: '120' },
      { field: 'TaskName', headerText: 'Task Name', width: '250', filter: this.filter },
      { field: 'StartDate', headerText: 'Start Date', width: '150' },
      { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    this.splitterSettings = {
      columnIndex: 2
    };

  }
}

interface Task {
  TaskID: number;
  TaskName: string;
  StartDate: Date;
  EndDate?: Date;
  Duration?: number;
  ParentID?: number;
  Progress?: number;
}

interface Column {
  field: string;
  headerText: string;
  width: string;
  filter?: FilterUI;
}

interface FilterUI {
  ui: {
    create: (args: { target: Element; column: Column }) => void;
    write: (args: { column: Column; target: Element; filteredValue: string }) => void;
    read: (args: { target: Element; column: Column; operator: string; fltrObj: any }) => void;
  };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Hide default filter icon while perform filtering through method

To hide the default filter icon from the UI when filtering is performed programmatically, apply the following CSS:

.e-filtermenudiv.e-icons.e-icon-filter {
      display: none;
    }

You can perform filtering programmatically by checking if args.currentTarget.id equals performFilter, and then calling filterByColumn method. If the condition is not met, use clearFiltering to reset filters via a button click.

import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { GanttModule, GanttComponent, FilterService } from '@syncfusion/ej2-angular-gantt';
import { ButtonAllModule } from '@syncfusion/ej2-angular-buttons';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GanttModule, ButtonAllModule],
  providers: [FilterService],
  encapsulation: ViewEncapsulation.None,
  template: `
    <div style="margin-bottom: 10px; display: flex; gap: 20px;">
      <button ejs-button id="performFilter" (click)="filterAction($event)">Filter Task Name Column</button>
      <button ejs-button id="clearFilter" (click)="filterAction($event)">Clear Filter</button>
    </div>
    <ejs-gantt #gantt height="370px" [allowFiltering]="true" [dataSource]="data" [taskFields]="taskSettings" [splitterSettings]="splitterSettings" [columns]="columns" [filterSettings]="filterSettings">
    </ejs-gantt>`,
  styles: [`
    .e-filtermenudiv.e-icons.e-icon-filter {
      display: none;
    }
  `]
})

export class AppComponent implements OnInit {
  @ViewChild('gantt', { static: true }) public ganttInstance!: GanttComponent;
  public data: object[] = [];
  public taskSettings = {};
  public splitterSettings = {};
  public filterSettings = {};
  public columns: object[] = [];

  ngOnInit(): void {
    this.data = [
      { TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 }
    ];
    this.taskSettings = {
      id: 'TaskID',
      name: 'TaskName',
      startDate: 'StartDate',
      duration: 'Duration',
      progress: 'Progress',
      parentID: 'ParentID'
    };
    this.columns = [
      { field: 'TaskID', headerText: 'Task ID', width: '120' },
      { field: 'TaskName', headerText: 'Task Name', width: '250'},
      { field: 'StartDate', headerText: 'Start Date', width: '150' },
      { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    this.splitterSettings = {
      columnIndex: 2
    };
  }

  public filterAction(args: MouseEvent): void {
    const targetId = (args.currentTarget as HTMLElement).id;
    if (targetId === 'performFilter') {
      (this.ganttInstance as GanttComponent).filterByColumn('TaskName', 'startswith', 'Project');
    } else {
      (this.ganttInstance as GanttComponent).clearFiltering();
    }
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Customize the default input component of filter menu dialog

To customize the default input components in the filter menu dialog, use the params property inside the column’s filter configuration. This allows you to override default settings such as autofill, spin buttons, and sort order. This allows you to override default settings based on the column type.

You can refer to the table below for supported column types, their default components, customization examples, and API references:

Column Type Default component Customization API Reference
String AutoComplete Eg: { params: { autofill: false }} AutoComplete API
Number NumericTextBox Eg: { params: { showSpinButton: false }} NumericTextBox API
Boolean DropDownList Eg: { params: { sortOrder:’Ascending’}} DropDownList API
Date DatePicker Eg: { params: { weekNumber: true }} DatePicker API
DateTime DateTimePicker Eg: { params: { showClearButton: true }} DateTimePicker API

The following sample demonstrates how to disable the autofill feature by setting the autofill property to false for the TaskName column, and how to disable the spin button by setting showSpinButton to false for the TaskID column.

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { GanttModule, FilterService } from '@syncfusion/ej2-angular-gantt';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GanttModule],
  providers: [FilterService],
  encapsulation: ViewEncapsulation.None,
  template: `
    <ejs-gantt #gantt height="370px" [allowFiltering]="true" [dataSource]="data" [taskFields]="taskSettings" [splitterSettings]="splitterSettings" [columns]="columns" [filterSettings]="filterSettings">
    </ejs-gantt>`
})

export class AppComponent implements OnInit {
  public data: object[] = [];
  public taskSettings = {};
  public splitterSettings = {};
  public filterSettings = {};
  public columns: object[] = [];
  public filter!: object;
  public taskFilter!: object;

  ngOnInit(): void {
    this.data = [
      { TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50 },
      { TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
      { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 },
      { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50 }
    ];
    this.taskSettings = {
      id: 'TaskID',
      name: 'TaskName',
      startDate: 'StartDate',
      duration: 'Duration',
      progress: 'Progress',
      parentID: 'ParentID'
    };
    this.filter = {
      params: { showSpinButton: false  }
    };
     this.taskFilter  = {
      params: { autofill: false }
    };
    this.columns = [
      { field: 'TaskID', headerText: 'Task ID', width: '120',filter: this.taskFilter },
      { field: 'TaskName', headerText: 'Task Name', width: '250', filter: this.filter },
      { field: 'StartDate', headerText: 'Start Date', width: '150' },
      { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    this.splitterSettings = {
      columnIndex: 2
    };
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Customizing filter menu operators list

The Syncfusion® Angular Gantt component allows customization of the default filter operator list using the filterSettings.operators property. This allows you to define a custom set of operators shown in the filter menu for each column type, improving usability and relevance.

You can configure operators for different types using the following options:

  • stringOperator – Custom operators for string columns.
  • numberOperator – Custom operators for number columns.
  • dateOperator – Custom operators for date columns.
  • booleanOperator – Custom operators for boolean columns.
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { GanttModule, FilterService } from '@syncfusion/ej2-angular-gantt';
import { FilterSettingsModel } from '@syncfusion/ej2-gantt';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GanttModule],
  providers: [FilterService],
  encapsulation: ViewEncapsulation.None,
  template: `
    <ejs-gantt #gantt height="370px" [allowFiltering]="true" [filterSettings]="filterOptions" [dataSource]="data" [taskFields]="taskSettings" [splitterSettings]="splitterSettings" [columns]="columns">
    </ejs-gantt>`
})

export class AppComponent implements OnInit {
  public data: object[] = [];
  public taskSettings: object = {};
  public splitterSettings: object  = {};
  public filterOptions?: FilterSettingsModel;
  public columns: object[] = [];

  ngOnInit(): void {
    this.data = [
      { TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019'), Approved: true },
      { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50, Approved: false },
      { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50, Approved: true },
      { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentID: 1, Progress: 50, Approved: false },
      { TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019'), Approved: true },
      { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50, Approved: false },
      { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50, Approved: true },
      { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentID: 5, Progress: 50, Approved: true }
    ];
    this.taskSettings = {
      id: 'TaskID',
      name: 'TaskName',
      startDate: 'StartDate',
      duration: 'Duration',
      progress: 'Progress',
      parentID: 'ParentID'
    };
    this.filterOptions = {
      type: 'Menu',
      operators: {
        stringOperator: [
          { value: 'startsWith', text: 'Starts With' },
          { value: 'endsWith', text: 'Ends With' },
          { value: 'contains', text: 'Contains' },
          { value: 'equal', text: 'Equal' },
          { value: 'notEqual', text: 'Not Equal' }
        ],
        numberOperator: [
          { value: 'equal', text: 'Equal' },
          { value: 'notEqual', text: 'Not Equal' },
          { value: 'greaterThan', text: 'Greater Than' },
          { value: 'lessThan', text: 'Less Than' }
        ],
        dateOperator: [
          { value: 'equal', text: 'Equal' },
          { value: 'notEqual', text: 'Not Equal' },
          { value: 'greaterThan', text: 'After' },
          { value: 'lessThan', text: 'Before' }
        ],
        booleanOperator: [
          { value: 'equal', text: 'Equal' },
          { value: 'notEqual', text: 'Not Equal' }
        ]
      }
    };
    this.columns = [
      { field: 'TaskID', headerText: 'Task ID', width: '120' },
      { field: 'TaskName', headerText: 'Task Name', width: '250' },
      { field: 'StartDate', headerText: 'Start Date', width: '150' },
      { field: 'Progress', headerText: 'Progress', width: '150' },
      { field: 'Approved', headerText: 'Approved', width: '140', type: 'boolean' }
    ];
    this.splitterSettings = {
      columnIndex: 2
    };
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));