Overview

  • Add custom DOM elements to the row headers.

  • React JSX components are detected automatically.

  • Other Scheduler row header customization options (raw HTML, active areas)

  • Includes a trial version of DayPilot Pro for JavaScript (see also 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.

Rendering JSX Component in React Scheduler Header

Custom HTML

react scheduler rendering jsx components in row headers html

The standard way of customizing the React Scheduler row headers is to use onBeforeRowHeaderRender event handler.

This event handler lets you change the row properties and/or set the HTML. However, it only works with HTML strings.

onBeforeRowHeaderRender: (args) => {
  args.row.html = `<span style='font-weight: bold'>${args.row.name}</span`>;
}

Active Areas

react scheduler rendering jsx components in row headers active areas

If you want to avoid raw HTML, you can also use active areas - special objects that let you insert a rectangle at a specified position, and define special behavior (it can open a context menu, a modal dialog, or run custom JavaScript function):

onBeforeRowHeaderRender: (args) => {
  args.row.areas = [
    {
      right: 3,
      top: 3,
      height: 12,
      width: 12,
      symbol: "icons/daypilot.svg#i-circle",
      style: "cursor: pointer",
      onClick: function (args) {
        const row = args.source;
        DayPilot.Modal.alert(row.name);
      }
    }
  ]
},

React JSX Component

react scheduler rendering jsx components in row headers component

In order to access the row header DOM element, the Scheduler introduces onBeforeRowHeaderDomAdd event handler that is called whenever the row header element is created and added to the DOM.

You can use it to define a custom DOM element that will be inserted in the row header cell:

onBeforeRowHeaderDomAdd: (args) => {
  args.target = "Cell";

  const cell = document.createElement("div");
  cell.innerText = args.row.name;

  args.element = cell;
},

You can also use args.element to specify custom JSX:

onBeforeRowHeaderDomAdd: (args) => {
  args.target = "Cell";
  args.element = <span style={{fontWeight: "bold"}}>{args.row.name}</span>;
},

It will work with custom React components as well:

onBeforeRowHeaderDomAdd: (args) => {
  args.target = "Cell";
  args.element = <SchedulerRow row={args.row} />;
},

SchedulerRow.js:

import React from 'react';

const SchedulerRow = ({ row }) => {
  return <div style={{ fontWeight: 'bold' }}>{row.name}</div>;
};

export default SchedulerRow;

Full Source Code

Scheduler.js (Scheduler Component)

import React, { useEffect, useRef, useState } from 'react';
import { DayPilot, DayPilotScheduler } from "daypilot-pro-react";
import SchedulerRow from "./SchedulerRow";

const Scheduler = () => {
  const [scheduler, setScheduler] = useState(null);
  const [events, setEvents] = useState([]);
  const [resources, setResources] = useState([]);
  const config = {
    timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
    scale: "Day",
    days: 31,
    startDate: "2025-01-01",
    timeRangeSelectedHandling: "Enabled",
    rowHeaderWidth: 130,
    onTimeRangeSelected: async (args) => {
      const scheduler = args.control;
      const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
      scheduler.clearSelection();
      if (modal.canceled) { return; }
      scheduler.events.add({
        start: args.start,
        end: args.end,
        id: DayPilot.guid(),
        resource: args.resource,
        text: modal.result
      });
    },
    treeEnabled: true,
    onBeforeRowHeaderRender: (args) => {
      args.row.areas = [
        {
          right: 3,
          top: 3,
          height: 12,
          width: 12,
          symbol: "icons/daypilot.svg#i-circle",
          style: "cursor: pointer",
          onClick: function (args) {
            const row = args.source;
            DayPilot.Modal.alert(row.name);
          }
        }
      ]
    },
    onBeforeRowHeaderDomAdd: (args) => {
      args.target = "Cell";
      args.element = <SchedulerRow row={args.row}/>;
    },
  };

  useEffect(() => {

    const events = [
      {
        id: 1,
        text: "Event 1",
        start: "2025-01-02T00:00:00",
        end: "2025-01-05T00:00:00",
        resource: "A"
      },
      {
        id: 2,
        text: "Event 2",
        start: "2025-01-03T00:00:00",
        end: "2025-01-10T00:00:00",
        resource: "C",
        barColor: "#38761d",
        barBackColor: "#93c47d"
      },
      {
        id: 3,
        text: "Event 3",
        start: "2025-01-02T00:00:00",
        end: "2025-01-08T00:00:00",
        resource: "D",
        barColor: "#f1c232",
        barBackColor: "#f1c232"
      },
      {
        id: 4,
        text: "Event 3",
        start: "2025-01-02T00:00:00",
        end: "2025-01-08T00:00:00",
        resource: "E",
        barColor: "#cc0000",
        barBackColor: "#ea9999"
      }
    ];
    setEvents(events);

    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"}
    ];
    setResources(resources);

  }, [scheduler]);

  return (
    <div>
      <DayPilotScheduler
        {...config}
        events={events}
        resources={resources}
        controlRef={setScheduler}
      />
    </div>
  );
}
export default Scheduler;