
| Demo | |
|---|---|
| Downloads | |
| Languages | TypeScript |
| Technologies | angular |
Overview
Learn how to filter events in real time using the specified text in the weekly Angular calendar.
You can also filter events by type (“reservation”, “maintenance”).
Both filters can be combined and applied at once.
Includes a trial version of DayPilot Pro for JavaScript (see License below).
This tutorial focuses on the Event Filtering feature. For an introductory tutorial on the Angular Calendar component, please see the Angular Calendar: Day/Week/Month Views (Open-Source) tutorial.
License
Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.
Filtering Events By Name in Angular Calendar

In this example, we will add a text input control above the Calendar. It will detect text changes using Angular’s ngModelChange event and apply the filter to the Calendar component after the bound value changes.
The standalone component imports FormsModule to enable ngModel. HTML template:
<input name="filterText" [(ngModel)]="filterText" type="text" placeholder="Filter" (ngModelChange)="filter()">The current value of the input field is stored in the filterText property:
filterText: string = "";As the user types the filter text, our component calls the filter() method to filter the events:
filter(): void {
const params = {
text: this.filterText,
// ...
};
this.calendar.control.events.filter(params);
}The excerpt shows the text part of the filter; the combined version below also supplies the event type. This method creates a filter parameters object and applies the filter by calling the events.filter() method.
When the filter is applied, the Calendar component calls the onEventFilter event handler for every event to evaluate whether it should be displayed or not, depending on the parameters.
The text rule in config.onEventFilter hides events that don’t contain the specified text. It converts the filter text and the event text to uppercase to make the filter case-insensitive.
onEventFilter: (args) => {
const filterText = args.filterParam.text || "";
const eventText = args.e.text() || "";
const textMatches = eventText.toUpperCase().indexOf(filterText.toUpperCase()) !== -1;
// ...
if (!textMatches) {
args.visible = false;
}
// ...
},Filtering Events by Type in Angular Calendar

The same approach can be used when filtering Calendar events by type.
We will add a drop-down list with event types to the toolbar:
<select name="filterType" [(ngModel)]="filterType" (ngModelChange)="filter()">
<option value="all">All</option>
<option value="reservation">Reservation</option>
<option value="maintenance">Maintenance</option>
</select>The selected value is available using the filterType property:
filterType: string = "all";The filter() method will store the selected value in the type property of the filter parameters and call events.filter():
filter(): void {
const params = {
// ...
type: this.filterType
};
this.calendar.control.events.filter(params);
}Each event stores its category in a custom type property. The type rule in the onEventFilter event handler checks whether the event type corresponds to the selected value and hides other event types:
onEventFilter: (args) => {
// ...
const filterType = args.filterParam.type || "all";
const eventType = args.e.data.type || "";
const typeMatches = filterType === "all" || filterType === eventType;
// ...
if (!typeMatches) {
args.visible = false;
}
},Using a Complex Event Filter

In this step, we will combine the text and type rules in our Angular app. The preceding excerpts focused on one rule at a time; the complete handler applies both rules at once.
The filter() method needs to set both criteria:
filter(): void {
const params = {
text: this.filterText,
type: this.filterType
};
this.calendar.control.events.filter(params);
}And the onEventFilter event handler checks both rules. If any of them doesn’t match, the event is marked as hidden:
onEventFilter: (args) => {
const filterText = args.filterParam.text || "";
const eventText = args.e.text() || "";
const textMatches = eventText.toUpperCase().indexOf(filterText.toUpperCase()) !== -1;
const filterType = args.filterParam.type || "all";
const eventType = args.e.data.type || "";
const typeMatches = filterType === "all" || filterType === eventType;
if (!textMatches) {
args.visible = false;
}
if (!typeMatches) {
args.visible = false;
}
},Clearing the Calendar Event Filter
To clear the filter, it is necessary to call the events.filter() method with a null parameter (or without a parameter). This will make the Calendar component display all events.
Our clearFilter() method also resets the filter input controls. Wrap the toolbar in a form with #filters="ngForm", give the controls their filterText and filterType names, and access the form using ViewChild. Calling resetForm() resets both the bound values and the displayed controls, even when Clear follows a text change immediately:
@ViewChild("filters")
filters!: NgForm;
// ...
clearFilter(): void {
this.filters.resetForm({filterText: "", filterType: "all"});
this.calendar.control.events.filter(null);
}Full Source Code
Here is the full source code of our Angular Calendar component, which allows filtering events using the specified text and event type.
The calendar.component.ts file defines the weekly Calendar UI and toolbar with filtering options. It implements the filtering rules. The config and events signals are passed directly to the DayPilot wrapper. After loading the events, events.set(result) updates the Calendar in the zoneless Angular app:
import {Component, ViewChild, AfterViewInit, signal} from "@angular/core";
import {DayPilot, DayPilotModule, DayPilotCalendarComponent} from "daypilot-pro-angular";
import {DataService} from "./data.service";
import {FormsModule, NgForm} from "@angular/forms";
@Component({
selector: 'calendar-component',
standalone: true,
imports: [DayPilotModule, FormsModule],
providers: [DataService],
template: `
<form class="toolbar" #filters="ngForm" (ngSubmit)="filter()">
<input name="filterText" [(ngModel)]="filterText" type="text" placeholder="Filter" (ngModelChange)="filter()">
<select name="filterType" [(ngModel)]="filterType" (ngModelChange)="filter()">
<option value="all">All</option>
<option value="reservation">Reservation</option>
<option value="maintenance">Maintenance</option>
</select>
<button type="button" (click)="clearFilter()">Clear</button>
</form>
<daypilot-calendar [config]="config" [events]="events" #calendar></daypilot-calendar>
`,
styles: [``]
})
export class CalendarComponent implements AfterViewInit {
@ViewChild("calendar")
calendar!: DayPilotCalendarComponent;
@ViewChild("filters")
filters!: NgForm;
filterText: string = "";
filterType: string = "all";
events = signal<DayPilot.EventData[]>([]);
config = signal<DayPilot.CalendarConfig>({
viewType: "Week",
timeRangeSelectedHandling: "Enabled",
onTimeRangeSelected: async (args) => {
const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
const calendar = args.control;
calendar.clearSelection();
if (modal.canceled) { return; }
calendar.events.add({
start: args.start,
end: args.end,
id: DayPilot.guid(),
text: modal.result
});
},
onEventFilter: (args) => {
const filterText = args.filterParam.text || "";
const eventText = args.e.text() || "";
const textMatches = eventText.toUpperCase().indexOf(filterText.toUpperCase()) !== -1;
const filterType = args.filterParam.type || "all";
const eventType = args.e.data.type || "";
const typeMatches = filterType === "all" || filterType === eventType;
if (!textMatches) {
args.visible = false;
}
if (!typeMatches) {
args.visible = false;
}
},
onBeforeEventRender: args => {
const isMaintenance = args.data["type"] === "maintenance";
const orange = "#f39c12c0";
const green = "#6aa84fc0";
args.data.backColor = isMaintenance ? orange : green;
args.data.borderColor = "darker";
args.data.fontColor = "#ffffff";
args.data.barHidden = true;
args.data.borderRadius = 15;
if (isMaintenance) {
const text = DayPilot.Util.escapeHtml(args.data.text || "");
args.data.html = `<div style='font-weight:bold;'>Maintenance</div><div>${text}</div>`;
}
}
});
constructor(private ds: DataService) {
}
filter(): void {
const params = {
text: this.filterText,
type: this.filterType
};
this.calendar.control.events.filter(params);
}
clearFilter(): void {
this.filters.resetForm({filterText: "", filterType: "all"});
this.calendar.control.events.filter(null);
}
ngAfterViewInit(): void {
const from = this.calendar.control.visibleStart();
const to = this.calendar.control.visibleEnd();
this.ds.getEvents(from, to).subscribe(result => {
this.events.set(result);
});
}
}The data.service.ts file generates sample events for the current week. Each event includes the type value used by the filter. The delayed observable simulates loading data; filtering is then performed on the loaded events in the browser.
import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
import {DayPilot} from "daypilot-pro-angular";
import {HttpClient} from "@angular/common/http";
@Injectable()
export class DataService {
events: any[] = [
{
id: 1,
start: DayPilot.Date.today().firstDayOfWeek().addHours(10),
end: DayPilot.Date.today().firstDayOfWeek().addHours(12),
text: "Event 1",
type: "reservation"
},
{
id: 2,
start: DayPilot.Date.today().firstDayOfWeek().addDays(1).addHours(12),
end: DayPilot.Date.today().firstDayOfWeek().addDays(1).addHours(16),
text: "Event 2",
type: "maintenance"
},
{
id: 3,
start: DayPilot.Date.today().firstDayOfWeek().addDays(1).addHours(10),
end: DayPilot.Date.today().firstDayOfWeek().addDays(1).addHours(11),
text: "Event 3",
type: "reservation"
},
{
id: 4,
start: DayPilot.Date.today().firstDayOfWeek().addDays(2).addHours(10),
end: DayPilot.Date.today().firstDayOfWeek().addDays(2).addHours(15),
text: "Event 4",
type: "reservation"
}
];
constructor(private http : HttpClient){
}
getEvents(from: DayPilot.Date, to: DayPilot.Date): Observable<any[]> {
// simulating an HTTP request
return new Observable(observer => {
setTimeout(() => {
observer.next(this.events);
}, 200);
});
// return this.http.get("/api/events?from=" + from.toString() + "&to=" + to.toString());
}
}History
September 17, 2026: Updated the sample to Angular 22 with signal-based Calendar bindings.
DayPilot




