Overview

  • How to change the date displayed by the React Scheduler component using “next” and “previous” buttons.

  • Load the new event data set before changing the view.

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.

Date Range Displayed by the React Scheduler

The React scheduler component lets you specify the visible range using a combination of startDate and days properties.

In the following example, the properties are set using attributes of the <DayPilotScheduler> component. You can also move the properties to the state (which is used to store the variable config values) but it’s important to remember that they will be reapplied during every state change.

The startDate property sets the first day to be displayed. The days property defines the number of visible days.

import React, {Component} from 'react';
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";

class Scheduler extends Component {

  constructor(props) {
    super(props);

    this.state = {
      timeHeaders: [{"groupBy": "Month"}, {"groupBy": "Day", "format": "d"}],
      scale: "Day",
      // ...
    };
  }


  render() {
    return (
      <div>
        <DayPilotScheduler
          days={30}
          startDate={"2022-06-01"}
          {...this.state}
          ref={this.schedulerRef}
        />
      </div>
    );
  }
}

export default Scheduler;

To display the current month, you can use DayPilot.Date helper methods which will calculate the right values for you using firstDayOfMonth() and daysInMonth() methods:

this.state = {
  startDate: DayPilot.Date.today().firstDayOfMonth(),
  days: DayPilot.Date.today().daysInMonth(),
  // ...
};

In order to change the date, you can either modify the state or use the direct API of DayPilot.Scheduler class.

In this tutorial, we will use the direct API. First, we need to get a reference to the DayPilot.Scheduler object using ref attribute and schedulerRef property:

import React, {Component} from 'react';
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";

class Scheduler extends Component {

  constructor(props) {
    super(props);

    this.schedulerRef = React.createRef();

    this.state = {

      // ...
    };
  }

  get scheduler() {
    return this.schedulerRef.current.control;
  }


  render() {
    return (
      <div>
        <DayPilotScheduler
          {...this.state}
          ref={this.schedulerRef}
        />
      </div>
    );
  }
}

export default Scheduler;

The scheduler object is now accessible using the this.scheduler getter.

“Previous” Button

First, you need to add the <button> element to JSX:

<button onClick={ev => this.previous()}>Previous</button>

The previous() method reads the current start using visibleStart() method and calculates the new start (newStart variable) using addMonths() method.

Event handler:

previous() {
  const start = this.scheduler.visibleStart();
  const newStart = start.addMonths(-1);
  
  this.scheduler.update({
    startDate: newStart,
    days: newStart.daysInMonth()
  });
}

In a typical React application, it will be necessary to load the event data for the new range. Here is an example that loads events using Axios and updates the Scheduler events together with startDate and days.

async previous() {

  const start = this.scheduler.visibleStart();
  const newStart = start.addMonths(-1);
  const newEnd = start.addMonths(1);

  const {data} = await axios.get(`/events?from={newStart}&to=${newEnd}`);

  this.scheduler.update({
    startDate: newStart,
    days: newStart.daysInMonth(),
    events: data
  });
}

“Next” Button

The implementation of the “next” button is very similar. When calculating the newStart value, we add one month instead of subtracting it.

JSX:

<button onClick={ev => this.next()}>Next</button>

This is a simplified next() event that only changes the visible range, without loading events:

next() {
  const start = this.scheduler.visibleStart();
  const newStart = start.addMonths(1);
  
  this.scheduler.update({
    startDate: newStart,
    days: newStart.daysInMonth()
  });
}

And here is a full implementation that loads events from a remote URL using Axios, waits for the result and updates the React scheduler:

async next() {

  const start = this.scheduler.visibleStart();
  const newStart = start.addMonths(1);
  const newEnd = start.addMonths(1);

  const {data} = await axios.get(`/events?from={newStart}&to=${newEnd}`);

  this.scheduler.update({
    startDate: newStart,
    days: newStart.daysInMonth(),
    events: data
  });
}

Full Source Code

This is the full source code of a simple React application that changes the Scheduler dates using custom “next” and “previous” buttons.

import React, {Component} from 'react';
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";

class Scheduler extends Component {

  constructor(props) {
    super(props);

    this.schedulerRef = React.createRef();

    this.state = {
      timeHeaders: [{"groupBy": "Month"}, {"groupBy": "Day", "format": "d"}],
      scale: "Day",
      timeRangeSelectedHandling: "Enabled",
      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
        });
      },
    };
  }

  get scheduler() {
    return this.schedulerRef.current.control;
  }

  componentDidMount() {

    const resources = [
      {name: "Resource A", id: "A"},
      {name: "Resource B", id: "B"},
      {name: "Resource C", id: "C"},
      {name: "Resource D", id: "D"},
      {name: "Resource E", id: "E"},
      {name: "Resource F", id: "F"},
      {name: "Resource G", id: "G"}
    ];

    const events = [
      {
        id: 1,
        text: "Event 1",
        start: "2022-06-02T00:00:00",
        end: "2022-06-05T00:00:00",
        resource: "A"
      },
      // ...
    ];

    this.scheduler.update({
      events,
      resources
    });

  }

  previous() {
    const start = this.scheduler.visibleStart();
    const newStart = start.addMonths(-1);

    this.scheduler.update({
      startDate: newStart,
      days: newStart.daysInMonth()
    });
  }

  next() {

    const start = this.scheduler.visibleStart();
    const newStart = start.addMonths(1);

    this.scheduler.update({
      startDate: newStart,
      days: newStart.daysInMonth()
    });
  }

/*
  async next() {

    const start = this.scheduler.visibleStart();
    const newStart = start.addMonths(1);
    const newEnd = start.addMonths(1);

    const {data} = await axios.get(`/events?from={newStart}&to=${newEnd}`);

    this.scheduler.update({
      startDate: newStart,
      days: newStart.daysInMonth(),
      events: data
    });
  }
*/

  render() {
    return (
      <div>
        <div className={"toolbar"}>
          <button onClick={ev => this.previous()}>Previous</button>
          <button onClick={ev => this.next()}>Next</button>
        </div>
        <DayPilotScheduler
          days={30}
          startDate={"2022-06-01"}
          {...this.state}
          ref={this.schedulerRef}
        />
      </div>
    );
  }
}

export default Scheduler;