

Angular Scheduler: Row Searching Tutorial | DayPilot Code
source link: https://code.daypilot.org/14888/angular-scheduler-row-searching-tutorial
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Features
Find Angular Scheduler rows that match the specified rule and highlight them using the built-in row selection feature.
This example searches by name (or a part of it) but you can easily extend the logic to include other criteria.
Click the "Find" button again to find and highlight the next row that matches the rule.
The current position and the total number of matching rows are displayed next to the "Find" button.
Includes a trial version of DayPilot Pro for JavaScript (see License below)
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.
Live Demo
Find and Highlight Scheduler Row by Name
Lets start with a simple search logic that finds the first row that includes the search text in its name.
In order to avoid the project setup and Scheduler configuration overhead, we will generate a new Angular project with pre-configured Scheduler component using the UI Builder online app. The Scheduler component can be found in src/app/scheduler/scheduler.component.ts file.
Now we can add a search <input>
and a "Find" button to the HTML template of SchedulerComponent class:
<input [(ngModel)]="search.text"> <button (click)="search.findRow()" class="find">Find</button>
All the search-related properties and logic will be wrapped in search property of SchedulerComponent class so you can extract it easily and use in your own project:
export class SchedulerComponent implements AfterViewInit { @ViewChild('scheduler', {static: false}) scheduler!: DayPilotSchedulerComponent; events: any[] = []; search: any = { text: '', findRow: () => { const scheduler = this.scheduler.control; const search = this.search; scheduler.rows.selection.clear(); const criteria = (r: DayPilot.Row) => r.name.toLowerCase().includes(search.text.toLowerCase()); const row = scheduler.rows.find(criteria); if (row) { scheduler.rows.selection.add(row); if (!scheduler.getViewPort().resources.includes(row.id)) { scheduler.scrollToResource(row); } } }, }; config: DayPilot.SchedulerConfig = { timeHeaders: [{groupBy: 'Month'}, {groupBy: 'Day', format: 'd'}], scale: 'Day', days: 31, startDate: '2021-12-01', // ... }; // ... }
The search.findRow() method is the core of the search implementation.
It clears the existing row selection:
scheduler.rows.selection.clear();
Then it searches for the first row that includes the specified text:
const criteria = (r: DayPilot.Row) => r.name.toLowerCase().includes(search.text.toLowerCase()); const row = scheduler.rows.find(criteria);
If found, the row is highlighted using the built-in row selecting feature of the Angular Scheduler component:
if (row) { scheduler.rows.selection.add(row); }
We also need to make sure that the highlighted row is visible. The findRow() method checks the current viewport of the Scheduler and scrolls to the target row if needed:
if (row) { scheduler.rows.selection.add(row); if (!scheduler.getViewPort().resources.includes(row.id)) { scheduler.scrollToResource(row); } }
Find the Next Matching Row
In this step, we will extend the search logic to support the find next functionality:
Updated HTML template:
<input [(ngModel)]="search.text"> <button (click)="search.findRow()" class="find">Find</button> {{search.index}}/{{search.total}}
Updated search object:
search: any = { text: '', lastIndex: -1, lastText: null, index: 0, total: 0, findRow: () => { const scheduler = this.scheduler.control; const search = this.search; if (search.lastText !== search.text) { search.lastIndex = -1; search.index = 0; scheduler.rows.selection.clear(); } search.lastText = search.text; const criteria = (r: DayPilot.Row) => r.name.toLowerCase().includes(search.text.toLowerCase()); const all = scheduler.rows.all().filter(criteria); const row = scheduler.rows.find(criteria, search.lastIndex + 1); if (row) { search.index += 1; scheduler.rows.selection.clear(); search.lastIndex = row.index; scheduler.rows.selection.add(row); if (!scheduler.getViewPort().resources.includes(row.id)) { scheduler.scrollToResource(row); } } search.total = all.length; } };
This makes our search object more complex. In addition to the search text (text), we need to keep track of the last search text so we can detect a change and start from the beginning (lastText), the index of the row that is highlighted (lastIndex), the total number of matching rows (total) and the position of the current selection in the matching rows (index).
The findRow() method uses the existing criteria function to calculate the total number of matching rows:
const all = scheduler.rows.all().filter(criteria); // ... search.total = all.length;
The Clear Button
And the last thing to add is the "clear" button that resets the search text and clear the row highlighting.
HTML template:
<button (click)="search.clear()">×</button>
clear() method:
search = { // ... clear: () => { const scheduler = this.scheduler.control; const search = this.search; search.text = ''; search.lastText = ''; search.lastIndex = -1; search.index = 0; search.total = 0; scheduler.rows.selection.clear(); } };
Full Source Code
Here is the source code of the scheduler.component.ts file with the complete row searching implementation:
import {Component, ViewChild, AfterViewInit} from '@angular/core'; import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular'; import {DataService} from './data.service'; @Component({ selector: 'scheduler-component', template: ` <div class="toolbar"> <input [(ngModel)]="search.text"> <button (click)="search.findRow()" class="find">Find</button><button (click)="search.clear()">×</button> {{search.index}}/{{search.total}} </div> <daypilot-scheduler [config]="config" [events]="events" #scheduler></daypilot-scheduler>`, styles: [` .toolbar { font-size: 14px; margin: 10px 0px; } input { padding: 6px; } button { background-color: #f3f3f3; border: 1px solid #c0c0c0; color: #333; padding: 6px 6px; cursor: pointer; margin-right: 5px; } button.find { width: 100px; } `] }) export class SchedulerComponent implements AfterViewInit { @ViewChild('scheduler', {static: false}) scheduler!: DayPilotSchedulerComponent; events: any[] = []; search: any = { text: '', lastIndex: -1, lastText: null, index: 0, total: 0, findRow: () => { const scheduler = this.scheduler.control; const search = this.search; if (search.lastText !== search.text) { search.lastIndex = -1; search.index = 0; scheduler.rows.selection.clear(); } search.lastText = search.text; const criteria = (r: DayPilot.Row) => r.name.toLowerCase().includes(search.text.toLowerCase()); const all = scheduler.rows.all().filter(criteria); const row = scheduler.rows.find(criteria, search.lastIndex + 1); if (row) { search.index += 1; scheduler.rows.selection.clear(); search.lastIndex = row.index; scheduler.rows.selection.add(row); if (!scheduler.getViewPort().resources.includes(row.id)) { scheduler.scrollToResource(row); } } search.total = all.length; }, clear: () => { const scheduler = this.scheduler.control; const search = this.search; search.text = ''; search.lastText = ''; search.lastIndex = -1; search.index = 0; search.total = 0; scheduler.rows.selection.clear(); } }; config: DayPilot.SchedulerConfig = { timeHeaders: [{groupBy: 'Month'}, {groupBy: 'Day', format: 'd'}], scale: 'Day', days: 31, startDate: '2021-12-01', onTimeRangeSelected: async (args) => { const dp = this.scheduler.control; const modal = await DayPilot.Modal.prompt('Create a new event:', 'Event 1'); dp.clearSelection(); if (!modal.result) { return; } dp.events.add({ start: args.start, end: args.end, id: DayPilot.guid(), resource: args.resource, text: modal.result }); }, treeEnabled: true, }; constructor(private ds: DataService) { } ngAfterViewInit(): void { this.ds.getResources().subscribe(result => this.config.resources = result); const from = this.scheduler.control.visibleStart(); const to = this.scheduler.control.visibleEnd(); this.ds.getEvents(from, to).subscribe(result => { this.events = result; }); } }
Recommend
-
26
FeaturesAngular Scheduler component with support for row filtering from DayPilot Pro for JavaScriptReal-time filtering by row nameAllow...
-
14
OverviewAngular 12 Scheduler componentIncludes the required boilerplate and it ready to runUses a local data source for simplicityIncludes a trial version of
-
35
FeaturesThis project uses Angular Scheduler component that displays a timeline for multiple resourcesIf none of the predefined Scheduler timeline
-
21
How to change the Angular Scheduler component appearance using a CSS theme. You can use one of the predefined themes or create your own theme using an online tool.
-
28
How to add action controls to the Angular Scheduler row headers: clickable icons, hyperlinks, context menu buttons.
-
15
OverviewThe Angular Scheduler component can display frozen rows at the top and/or bottom of the grid.You can use the dynamic content generation events...
-
16
FeaturesHighlights global holidays using custom grid cell background color + timeline barHighlights per-resource holidays using custom background colorAngular 12 application
-
11
FeaturesUses Angular Scheduler component from DayPilot Pro for JavaScriptThe Scheduler displays a couple of events visually joint using event links...
-
35
Angular 12 project that shows how to dynamically configure the Scheduler context menu (for events and rows).
-
23
OverviewHow to configure the Angular Scheduler component to support infinite scrolling and load events on demandHow to pre-load events for the areas cl...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK