javascript scheduler event filtering

The JavaScript Scheduler component supports fast client-side filtering. It lets you hide events that don’t match the specified criteria.

You can use it to implement following features:

  • Fast search (show only events that contain the specified text)

  • Show/hide events of a certain type

How to implement event filter

1. To apply the filter, call events.filter() with a non-null value. It can be a dynamic value (a text from a “search” input field), a complex object (with multiple filter criteria) or a fixed value (e.g. "hideTentativeEvents").

2. The Scheduler uses the onEventFilter event handler to determine which events match the filter. You need to provide the implementation, based on your rules.

By default, all events are visible - you need to set args.visible = false for events that don't match the filter. The original event data object (including custom fields) is accessible as args.e.data.

onEventFilter: (args) => {
  if (args.filter === "hideTentativeEvents" && args.e.data.type === "tentative") {
    args.visible = false;
  }
}

To apply the filter, call events.filter():

dp.events.filter("hideTentativeEvents");

This example assumes the event object has a type property:

{
  id: 1,
  start: "2024-10-01T00:00:00",
  end: "2024-10-05T00:00:00",
  text: "Meeting",
  resource: "A",
  type: "tentative"
}

3. To clear the filter, call events.filter() without any parameter:

dp.events.filter();

See also

Examples

Text filter

The code includes a text input field and a clear button for user input. When a user types into the filter input field, an event listener attached to the keyup event initiates the filtering process. This filtering process is implemented by the onEventFilter event of the DayPilot.Scheduler object. It compares the entered filter text (ignoring case) with the text of each Scheduler event. If an event doesn't contain the entered text, it is hidden from view.

When the clear button is clicked, it clears the content of the filter input field and resets the filter, making all Scheduler events visible again. This is done by calling dp.events.filter(null).

<div class="space">
  Filter: <input id="filter" /> <a href="#" id="clear">Clear</a>
</div>

<div id="dp"></div>

<script>

  const dp = new DayPilot.Scheduler("dp", {
    onEventFilter: (args) => {
      // display only events that contain the specified text, case insensitive
      if (args.e.text().toUpperCase().indexOf(args.filter.toUpperCase()) === -1) {
        args.visible = false;
      }
    }
  });
  dp.init();


  const app = {
    elements: {
      filter: document.querySelector("#filter"),
      clear: document.querySelector("#clear")
    },
    init() {
      app.elements.filter.addEventListener("keyup", () => {
        const query = app.elements.filter.value;
        dp.events.filter(query);
      });
      app.elements.clear.addEventListener("click", (ev) => {
        ev.preventDefault();
        app.elements.filter.value = "";
        dp.events.filter(null);
      });
    }
  };
  app.init();

</script>

Text filter + display overlapping events

This filter implementation displays events that contain the searched text and any events that overlap with them.

onEventFilter: (args) => {
  const events = dp.events.forRange(args.e.start(), args.e.end()).filter(e => e.resource() === args.e.resource());

  const textFound = events.some((e) => {
      return e.text().toUpperCase().indexOf(args.filter.toUpperCase()) > -1;
  });

  if (!textFound) {
      args.visible = false;
  }
}

Live Demo

API: onEventFilter.

The buttons below filter the loaded collection for Planning or clear the filter. onEventFilter changes visibility while preserving the source events.

The framework examples use DayPilot Pro. For installation, see the Angular, React or Vue Scheduler guide.

Angular

Keep onEventFilter in the config and use the @ViewChild control to call events.filter() from the button methods.

import {Component, ViewChild} from "@angular/core";
import {DayPilot, DayPilotModule, DayPilotSchedulerComponent} from "daypilot-pro-angular";

@Component({
  selector: "app-scheduler-example",
  standalone: true,
  imports: [DayPilotModule],
  template: `
    <button (click)="action0()">Show Planning</button>
    <button (click)="action1()">Clear filter</button>
    <daypilot-scheduler [config]="config" #scheduler></daypilot-scheduler>
  `
})
export class SchedulerExampleComponent {
  @ViewChild("scheduler") scheduler!: DayPilotSchedulerComponent;
  config: DayPilot.SchedulerConfig = {
    startDate: "2026-11-01",
    days: 30,
    scale: "Day",
    timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "d"}],
    resources: [{id: "A", name: "Room A"}, {id: "B", name: "Room B"}],
    events: [{id: 1, text: "Planning", resource: "A", start: "2026-11-03", end: "2026-11-06"}, {id: 2, text: "Delivery", resource: "B", start: "2026-11-08", end: "2026-11-11"}],
    onEventFilter: args => { args.visible = args.e.text().toLowerCase().includes(args.filterParam.toLowerCase()); }
  };
  async action0() {
    const dp = this.scheduler.control;
    dp.events.filter("planning");
  }
  async action1() {
    const dp = this.scheduler.control;
    dp.events.filter(null);
  }
}
  • Angular Scheduler: Event Filtering

    React

    Pass onEventFilter as a prop and retain the control with controlRef. Both button handlers operate on that control's event collection.

    import React, {useRef} from "react";
    import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";
    
    export default function SchedulerExample() {
      const scheduler = useRef(null);
      async function action0() {
        const dp = scheduler.current;
        dp.events.filter("planning");
      }
      async function action1() {
        const dp = scheduler.current;
        dp.events.filter(null);
      }
      return <div>
        <button onClick={action0}>Show Planning</button>
        <button onClick={action1}>Clear filter</button>
        <DayPilotScheduler
          controlRef={control => { scheduler.current = control; }}
          startDate={"2026-11-01"}
          days={30}
          scale={"Day"}
          timeHeaders={[{groupBy: "Month"}, {groupBy: "Day", format: "d"}]}
          resources={[{id: "A", name: "Room A"}, {id: "B", name: "Room B"}]}
          events={[{id: 1, text: "Planning", resource: "A", start: "2026-11-03", end: "2026-11-06"}, {id: 2, text: "Delivery", resource: "B", start: "2026-11-08", end: "2026-11-11"}]}
          onEventFilter={args => { args.visible = args.e.text().toLowerCase().includes(args.filterParam.toLowerCase()); }}
        />
      </div>;
    }

    Vue

    Bind :onEventFilter to the script callback. The @click functions invoke filtering through scheduler.value.control.

    <script setup>
    import {ref} from "vue";
    import {DayPilot, DayPilotScheduler} from "daypilot-pro-vue";
    
    const scheduler = ref(null);
    const startDate = "2026-11-01";
    const days = 30;
    const scale = "Day";
    const timeHeaders = [{groupBy: "Month"}, {groupBy: "Day", format: "d"}];
    const resources = [{id: "A", name: "Room A"}, {id: "B", name: "Room B"}];
    const events = [{id: 1, text: "Planning", resource: "A", start: "2026-11-03", end: "2026-11-06"}, {id: 2, text: "Delivery", resource: "B", start: "2026-11-08", end: "2026-11-11"}];
    const onEventFilter = args => { args.visible = args.e.text().toLowerCase().includes(args.filterParam.toLowerCase()); };
    async function action0() {
      const dp = scheduler.value.control;
      dp.events.filter("planning");
    }
    async function action1() {
      const dp = scheduler.value.control;
      dp.events.filter(null);
    }
    </script>
    
    <template>
      <div>
        <button @click="action0">Show Planning</button>
        <button @click="action1">Clear filter</button>
        <DayPilotScheduler ref="scheduler"
          :startDate="startDate"
          :days="days"
          :scale="scale"
          :timeHeaders="timeHeaders"
          :resources="resources"
          :events="events"
          :onEventFilter="onEventFilter"
        />
      </div>
    </template>

    ASP.NET WebForms

    Use ClientState to persist the filter parameters. 

    You can store the filter settings in .clientState property on the client side:

    dps.clientState.filterText = 'text';
    dps.clientState.filterType = 'finished';

    ClientState is persisted and updated with every callback (until you reload the page) and it's accessible on the server side.

    string filterText = (string) DayPilotScheduler1.ClientState["filterText"];
    string filterType = (string) DayPilotScheduler1.ClientState["filterType"];
    
    DayPilotScheduler1.DataSource = LoadData(filterText, filterType);
    DayPilotScheduler1.DataBind();
    DayPilotScheduler1.Update();

    ASP.NET MVC

    Use ClientState to persist the filter parameters. 

    You can store the filter settings in .clientState property on the client side:

    dps.clientState.filterText = 'text';
    dps.clientState.filterType = 'finished';

    ClientState is persisted and updated with every callback (until you reload the page) and it's accessible on the server side.

    string filterText = (string) ClientState["filterText"];
    string filterType = (string) ClientState["filterType"];
    
    Events = LoadEvents(filterText, filterType);
    Update();

    Availability

    Availability of this feature in DayPilot editions:

    ProductLitePro
    DayPilot for JavaScript
    DayPilot for ASP.NET WebForms
    DayPilot for ASP.NET MVC
    DayPilot for Java