Overview

  • How to add next/previous buttons that will change the current view of the Angular Scheduler component

  • Event loading based on view change detection event that is fired after every Scheduler update

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.

How to Configure the Scheduler to Display the Current Month

angular scheduler next previous current month

The visible date range of the Angular Scheduler component can be set using startDate and days properties of the config object. The following configuration will display October 2021:

import {Component} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import SchedulerConfig = DayPilot.SchedulerConfig;

@Component({
  selector: 'scheduler-component',
  template: `<daypilot-scheduler [config]="config"></daypilot-scheduler>`,
  styles: [`/* ... */`]
})
export class SchedulerComponent {

  config: SchedulerConfig = {
    days: 31,
    startDate: "2021-10-01,
    
    // ...

    timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
    scale: "Day",
  };

}

How to Change the Month using Next, Previous and Today Buttons

angular scheduler next previous today buttons

If you want to change the current range using Next/Today/Previous buttons you need to add a (click) handler that changes the startDate value. In case of a month view, it is also necessary to update the days value because the number of days depends on the selected month:

HTML template:

<button (click)="previous()">Previous</button>
<button (click)="today()">Today</button>
<button (click)="next()">Next</button>

TypeScript:

previous(): void {
  this.config.startDate = new DayPilot.Date(this.config.startDate).addMonths(-1);
  this.config.days = this.config.startDate.daysInMonth();
}

today(): void {
  this.config.startDate = DayPilot.Date.today().firstDayOfMonth();
  this.config.days = this.config.startDate.daysInMonth();
}

next(): void {
  this.config.startDate = new DayPilot.Date(this.config.startDate).addMonths(1);
  this.config.days = this.config.startDate.daysInMonth();
}

Loading Scheduler Events for the New Month

angular scheduler next previous loading events

The Scheduler component detects the changes in the config object automatically and updates the view. When changing the visible month, it's necessary to load the events for the new date range. 

It's possible to add the event-loading code to the next(), previous() and today() methods but we will use (viewChange) event that is fired whenever the Scheduler component detects a config change and updates itself. This will ensure that Scheduler always loads the correct data set.

HTML template:

<daypilot-scheduler [config]="config" [events]="events" (viewChange)="schedulerViewChanged($event)"></daypilot-scheduler>

TypeScript

export class SchedulerComponent implements AfterViewInit {

  events: any[] = [];

  // ...

  schedulerViewChanged(args: any) {
    if (args.visibleRangeChanged) {
      const from = this.scheduler.control.visibleStart();
      const to = this.scheduler.control.visibleEnd();
      this.ds.getEvents(from, to).subscribe(result => {
        this.events = result;
      });
    }
  }

}

You can see that we detect that the view change included a date range change by checking args.visibleRangeChanged property.

Full Source Code

import {Component, ViewChild, AfterViewInit} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import {DataService} from './data.service';
import SchedulerConfig = DayPilot.SchedulerConfig;

@Component({
  selector: 'scheduler-component',
  template: `

    <div class="toolbar">
        <button (click)="previous()">Previous</button>
        <button (click)="today()">Today</button>
        <button (click)="next()">Next</button>
    </div>
      <daypilot-scheduler [config]="config" [events]="events" (viewChange)="schedulerViewChanged($event)" #scheduler></daypilot-scheduler>

  `,
  styles: [`
    .toolbar {
        margin: 10px 0px;
    }

    .toolbar button {
        background-color: #f3f3f3;
        border: 1px solid #c0c0c0;
        color: #333;
        padding: 8px 0px;
        width: 100px;
        border-radius: 2px;
        cursor: pointer;
        margin-right: 5px;
    }

  `]
})
export class SchedulerComponent implements AfterViewInit {

  @ViewChild('scheduler', {static: false})
  scheduler!: DayPilotSchedulerComponent;

  events: any[] = [];

  config: SchedulerConfig = {
    timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
    scale: "Day",
    days: 31,
    startDate: "2021-10-01",
    timeRangeSelectedHandling: "Enabled",
    onTimeRangeSelected: async (args) => {
      var 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,
  };

  constructor(private ds: DataService) {
  }

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

  previous(): void {
    this.config.startDate = new DayPilot.Date(this.config.startDate).addMonths(-1);
    this.config.days = this.config.startDate.daysInMonth();
  }

  today(): void {
    this.config.startDate = DayPilot.Date.today().firstDayOfMonth();
    this.config.days = this.config.startDate.daysInMonth();
  }

  next(): void {
    this.config.startDate = new DayPilot.Date(this.config.startDate).addMonths(1);
    this.config.days = this.config.startDate.daysInMonth();
  }

  schedulerViewChanged(args: any) {
    if (args.visibleRangeChanged) {
      const from = this.scheduler.control.visibleStart();
      const to = this.scheduler.control.visibleEnd();
      this.ds.getEvents(from, to).subscribe(result => {
        this.events = result;
      });
    }
  }

}