Features

  • This project uses Angular Scheduler component that displays a timeline for multiple resources

  • If none of the predefined Scheduler timeline scale options meet your needs you can generate your own timeline by defining an array of individual cells

  • You can also use custom cell duration (anything starting from 1 second)

  • This also allows creating a non-continuous timeline (certain time ranges are hidden)

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.

Scheduler with 30-Second Cells

This example uses config.timeline property to specify a custom timeline. This property is used if the Scheduler is switched to manual scale mode (scale: "Manual").

config: DayPilot.SchedulerConfig = {
  scale: "Manual",
  timeline: this.getTimeline(),
  // ...
};

The timeline is generated using getTimeline() method. It returns an array of timeline cells. The array items specify start and end of each timeline cell. 

The following implementation generates a timeline for the specified date (today is used if the target date is not set). Each cell has a duration of 30 seconds (that makes 2880 cells per day).

getTimeline(date?: DayPilot.Date | string): any[] {
  let day = new DayPilot.Date(date).getDatePart();

  let timeline = [];

  for (var i = 0; i < 2880; i++) {
    let start = day.addSeconds(i * 30);
    timeline.push({start: start, end: start.addSeconds(30) });
  }

  return timeline;
};

Source Code

scheduler.component.ts

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="space">
    <daypilot-navigator [config]="navConfig"></daypilot-navigator>
    </div>
    <div class="space">
    <daypilot-scheduler [config]="config" [events]="events" (viewChange)="schedulerViewChange()" #scheduler></daypilot-scheduler>
    </div>
  `,
  styles: [``]
})
export class SchedulerComponent implements AfterViewInit {

  @ViewChild('scheduler')
  scheduler!: DayPilotSchedulerComponent;

  events: any[] = [];

  config: DayPilot.SchedulerConfig = {
    locale: "en-us",
    cellWidthSpec: "Fixed",
    cellWidth: 20,
    crosshairType: "Header",
    timeHeaders: [
      {groupBy: "Day", format: "d MMMM, yyyy"},
      {groupBy: "Hour"},
      {groupBy: "Minute"}
      ],
    scale: "Manual",
    timeline: this.getTimeline(),
    onTimeRangeSelected: async args => {
      const dp = args.control;
      const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
      dp.clearSelection();
      if (modal.canceled) { return; }
      dp.events.add({
        start: args.start,
        end: args.end,
        id: DayPilot.guid(),
        resource: args.resource,
        text: modal.result
      });
    },
    treeEnabled: true,
  };

  navConfig: DayPilot.NavigatorConfig = {
    orientation: "Horizontal",
    showMonths: 3,
    cellHeight: 25,
    cellWidth: 25,
    dayHeaderHeight: 25,
    onTimeRangeSelected: args => {
      this.config.timeline = this.getTimeline(args.day);
    }
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    this.ds.getResources().subscribe(result => this.config.resources = result);
  }

  schedulerViewChange() {
    const from = this.scheduler.control.visibleStart();
    const to = this.scheduler.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

  getTimeline(date?: DayPilot.Date | string): any[] {
    let day = new DayPilot.Date(date).getDatePart();

    let timeline = [];

    for (var i = 0; i < 2880; i++) {
      let start = day.addSeconds(i * 30);
      timeline.push({start: start, end: start.addSeconds(30) });
    }

    return timeline;
  };

}