search envelope-o feed check
Home Unanswered Active Tags New Question
user comment-o

How to install DayPilot Pro & use in React code

Asked by Shruti Duggal
3 months ago.

Hi,

We are planning to purchase a license for this software. But prior to that need to check the compatibility of including this in our application. Can you let us know if npm install will work with this lib.
Is there any trial version which you can share along with steps of installation so that we can test.

BR
Shruti

Answer posted by Dan Letecky [DayPilot]
3 months ago.

Hi Shruti,

Thank you for choosing DayPilot Pro!

You can get a NPM link for a trial version here:

https://npm.daypilot.org/

The following documentation page describes how to start using the Scheduler component in a React application:
https://doc.daypilot.org/scheduler/react/

There are also tutorials available which include a downloadable React project:
https://code.daypilot.org/tutorials/react

You can use these tutorials as a starting point for the integration.

Comment posted by Anonymous
3 months ago.

We are getting the following error after trying the steps of installing the day pilot scheduler. We are using react version 16, react-dom -: version 16.
1) Cannot resolve the dependency of react-dom/client in react day pilot pro
2) this.scheduler.update gives the error

Comment posted by Dan Letecky [DayPilot]
3 months ago.

> 1) Cannot resolve the dependency of react-dom/client in react day pilot pro

You'll see this warning with DayPilot Pro version 2022.2.5264 and later. Since this version, DayPilot targets React 18 and previous versions will print this warning during compilation. The compiled React application should work fine, though.

Please see more:
https://javascript.daypilot.org/daypilot-pro-for-javascript-2022-2-5264/

> 2) this.scheduler.update gives the error

Could you please post the error message?

Comment posted by Dan Letecky [DayPilot]
3 months ago.

The example in the documentation used a ref callback to get access to the DayPilot.Scheduler object. In some cases, it keeps a reference to an outdated object that has been destroyed and that throws an exception.

I recommend switching to React.createRef() method (this is now updated in the documentation as well):

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

class Scheduler extends Component {

    constructor(props) {
        super(props);
        this.schedulerRef = React.createRef();
    }

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

    render() {
        return (
            <div>
                <button onClick={e => this.scheduler.message('Welcome!')}>Welcome</button>
                
                <DayPilotScheduler
                    ref={this.schedulerRef}
                />
            </div>
        );
    }
}

export default Scheduler;

Let me know if there is any problem with this solution.

Comment posted by Anonymous
3 months ago.

Please find the below error. Event after trying the this.schedulerRef = React.createRef();
the error is coming. Its working fine with react 18 but not with react 16 which is our requirement.

1) this.schedulerRef.update is not a function.

Comment posted by Dan Letecky [DayPilot]
3 months ago.

> 1) this.schedulerRef.update is not a function.

Please make sure that it is

this.scheduler.update()

or

this.schedulerRef.current.control.update();

The React.createRef() method should be available since React 16.3.

Comment posted by Anonymous
3 months ago.

Hi Team
We want to have the schedular with resources. In the didMount the following line is giving the error-:

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

Please find the class. We tried using this.schedulerRef.current.control.update(); also but issue is not resolved

class Scheduler extends Component {  

  undoService = new UndoService();

  constructor(props) {
    super(props);
    this.schedulerRef = React.createRef();

    this.state = {
      events:[],
      rowMoveHandling: "Update",
      onRowMove: args => {
        console.log("onRowMove", args);
      },
      rowMoveSameLevelOnly: true,
      config: {
        timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
        rowHeaderColumns : [
          { text: 'Resource', display: "name", sort: "name" }
         
        ],
        scale: "Day",
        days: 30,
        startDate: "2021-09-01",
        rowMarginBottom: 1,
        onBeforeEventRender: args => {
          if (args.data.backColor) {
            args.data.borderColor = "darker";
            args.data.fontColor = "white";
          }
          args.data.barHidden = true;
        },
        eventDeleteHandling: "Update",
        onTimeRangeSelected: async (args) => {
          const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
          this.schedulerRef.clearSelection();
          if (modal.canceled) { return; }

          const e = {
            start: args.start,
            end: args.end,
            id: DayPilot.guid(),
            resource: args.resource,
            text: modal.result
          };
          this.schedulerRef.events.add(e);
          this.undoService.add(e, "Event added");
        },
        onEventMoved: (args) => {
          this.undoService.update(args.e.data, "Event moved");
        },
        onEventResized: (args) => {
          this.undoService.update(args.e.data, "Event resized");
        },
        onEventDeleted: (args) => {
          this.undoService.remove(args.e.data, "Event removed");
        },
        onEventClick: async args => {     
          const dp = this.schedulerRef;    
          const modal =await DayPilot.Modal.prompt("Update event text:", args.e.text());
          this.schedulerRef.clearSelection();
          if (!modal.result) { return; }
          const e = args.e;
          e.data.text = modal.result;         
          dp.events.update(e);
          console.log("the events are");
          console.log(this.schedulerRef.events)
        },
        treeEnabled: true,
        rowCreateHandling: "Enabled",
        rowCreateText: "New group...",
        onRowCreate: args => {
  
          const row = {
            name: args.text,
            id: DayPilot.guid()
          }
          this.schedulerRef.rows.add(row);
  
        },
        rowMoveSameLevelOnly: true,
        rowMoveHandling: "Update",
        onRowMove: args => {
          console.log("onRowMove", args);
        },
        onBeforeRowHeaderRender: args => {
          args.row.areas = [
            {
              right: 6,
              top: 6,
              width: 18,
              height: 18,
              action: "ContextMenu",
              backColor: "#ffffff",
              symbol: "icons/daypilot.svg#minichevron-down-4",
              fontColor: "#cccccc",
              style: "border: 1px solid #ccc; cursor: pointer;",
              visibility: "Hover"
            }
          ]
        },

        contextMenuSelection: new DayPilot.Menu({
          items: [
            {
              text: "Paste",
              onClick: args => {
                console.log("the args are ");
                console.log(args);
                console.log("the clipboard is");
                console.log(this.clipboard)
                let e = this.clipboard[0];   
                console.log("the event is");
                console.log(e);   
                if (!e) {
                  return;
                }
                
               
                let start = e.data.start;                
                let end =e.data.end;
                let targetResource = args.source.resource;      
                let params = {
                  start: start,
                  end: end,
                  resource: targetResource,
                  text: e.text(),                
                  backColor: "#e69138",
                  id: DayPilot.guid(),
                };
                console.log("the params are");
                console.log(params);
               
               
              this.schedulerRef.events.add(params);
              
                 //this.createEvent(params).subscribe(result => this.schedulerRef.control.events.add(result));
              }
            }
              
              ]
        }),
        contextMenu: new DayPilot.Menu({
          items: [
            { text: "Edit", onClick: function (args) { } },
            { text: "Delete", onClick: function (args) {  } },
            {
              text: "Cut",
              onClick: args => {
                this.clipboard = [ args.source ];
              }
            },
            { text: "-"},
            { text: "Change background color", onClick: function (args) {            
                var e = args.source;
                e.data.backColor = "red";
               
              }
            },
            {text: "-"},
            { text: "Select", onClick: function (args) { } },
            {
              text: "Copy",
              onClick: args => {
                this.clipboard = [ args.source ];
              }
            },
            {
              text: "Replace",
              onClick: args => {
                console.log("the args are ");
                console.log(args);
                console.log("the clipboard is");
                console.log(this.clipboard)
                let e = this.clipboard[0];   
                console.log("the event is");
                console.log(e);   
                if (!e) {
                  return;
                }
                
               
                let start = e.data.start;                
                let end =e.data.end;
                let targetResource = args.source.resource;      
                let params = {
                  start: start,
                  end: end,
                  resource: targetResource,
                  text: e.text(),                
                  backColor: "#e69138",
                  id: DayPilot.guid(),
                };
                console.log("the params are");
                console.log(params);
               
               
              this.schedulerRef.events.add(params);
              
                 //this.createEvent(params).subscribe(result => this.schedulerRef.control.events.add(result));
              }
            }
           
          ]
        }),

        contextMenuResource: new DayPilot.Menu({
          onShow: args => {
            const row = args.source;
            const isParent = row.level === 0;
            args.menu.items[3].disabled = !isParent;
          },
          items: [
            {text: "Edit...", onClick: args => this.edit(args) },
            {text: "Delete...", onClick: args => this.delete(args) },
            {text: "-"},
            {text: "Add resource....", onClick: args => this.add(args)}
          ]
        })
      }
     
    };
   
  }

  doUndo() {
    if (typeof this.props.onUndo === "function") {
      this.props.onUndo();
    }
  }


  componentDidMount() {  
    const events = [
      {
        id: 1,
        text: "Event 1",
        start: "2021-09-02T00:00:00",
        end: "2021-09-05T00:00:00",
        resource: "A",
        backColor: "#e69138"
      },
      {
        id: 2,
        text: "Event 2",
        start: "2021-09-03T00:00:00",
        end: "2021-09-10T00:00:00",
        resource: "C",
        backColor: "#6aa84f"
      },
      {
        id: 3,
        text: "Event 3",
        start: "2021-09-02T00:00:00",
        end: "2021-09-08T00:00:00",
        resource: "D",
        backColor: "#3d85c6"
      },
      {
        id: 4,
        text: "Event 3",
        start: "2021-09-04T00:30:00",
        end: "2021-09-10T00:00:00",
        resource: "F",
        backColor: "#cc4125"
      },
      {
        id: 5,
        text: "Event 4",
        start: "2021-09-02T00:00:00",
        end: "2021-09-05T00:00:00",
        resource: "A",
        backColor: "#e69138"
      },
      {
        id: 6,
        text: "Event 5",
        start: "2021-09-03T00:00:00",
        end: "2021-09-10T00:00:00",
        resource: "C",
        backColor: "#6aa84f"
      },
      {
        id: 7,
        text: "Event 6",
        start: "2021-09-02T00:00:00",
        end: "2021-09-08T00:00:00",
        resource: "D",
        backColor: "#3d85c6"
      },
      {
        id: 8,
        text: "Event 7",
        start: "2021-09-04T00:00:00",
        end: "2021-09-10T00:00:00",
        resource: "F",
        backColor: "#cc4125"
      }
    ];

    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"}
    ];
   this.setState({events:events})
  
    // load resource and event data
    this.schedulerRef.update({      
      resources,
      events
    });

    this.undoService.initialize(events);
   

  }

  undo() {
    const action = this.undoService.undo();

    switch (action.type) {
      case "add":
        // added, need to delete now
        this.schedulerRef.events.remove(action.id);
        break;
      case "remove":
        // removed, need to add now
        this.schedulerRef.events.add(action.previous);
        break;
      case "update":
        // updated
        this.schedulerRef.events.update(action.previous);
        break;
      default:
        throw new Error("Unexpected action");
    }
  }

  redo() {
    const action = this.undoService.redo();

    switch (action.type) {
      case "add":
        // added, need to re-add
        this.schedulerRef.events.add(action.current);
        break;
      case "remove":
        // removed, need to remove again
        this.schedulerRef.events.remove(action.id);
        break;
      case "update":
        // updated, use the new version
        this.schedulerRef.events.update(action.current);
        break;
      default:
        throw new Error("Unexpected action");
    }
  }

  render() {
   
    return <div>
        <Buttons service={this.undoService} onUndo={() => this.undo()} onRedo={() => this.redo()} />
        <DayPilotScheduler
          {...this.state.config}
          ref={component => {
            this.schedulerRef = component && component.control;
          }}
          onChange={(s) => console.log(s)}
        />
        <h2>History</h2>
        <History service={this.undoService} />
      </div>;
  }
}

export default Scheduler;
Comment posted by Dan Letecky [DayPilot]
3 months ago.

In order to use React.createRef(), you need to change the "ref" attribute as follows:

ref={this.schedulerRef}

To access the DayPilot.Scheduler object, you need to use this:

const scheduler = this.schedulerRef.current.control;
Comment posted by Anonymous
3 months ago.

Hi Team
Could you pls tell me which line to be replaced with this. As I did the changes in the constructor. I am getting this error.
TypeError: Cannot read properties of null (reading 'control')

Following changes I did-:

 constructor(props) {
    super(props);
    this.schedulerRef = React.createRef();
    this.scheduler = this.schedulerRef.current.control;
}
    this.scheduler.update({      
      resources,
      events
    });

Comment posted by Dan Letecky [DayPilot]
3 months ago.

The "current" property needs to be resolved dynamically. The best way is to use a getter. I'm pasting the example from https://doc.daypilot.org/scheduler/react/:

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

class Scheduler extends Component {

    constructor(props) {
        super(props);
        this.schedulerRef = React.createRef();
    }

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

    render() {
        return (
            <div>
                <button onClick={e => this.scheduler.message('Welcome!')}>Welcome</button>
                
                <DayPilotScheduler
                    ref={this.schedulerRef}
                />
            </div>
        );
    }
}

export default Scheduler;

Now the DayPilot.Scheduler instance is accessible using "this.scheduler". However, it requires the component to be rendered first, so you need to move the event loading code to componentDidMount():

componentDidMount() {  
  const events = [ /* ... */ ];
  const resources = [ /* ... */ ];
  this.scheduler.update({
    events,
    resources
  });
}

Please let me know if there is any problem.

Comment posted by Shruti Duggal
3 months ago.

Hi Dan,

Thanks for the prompt responses. We want to get a quote to purchase DayPilot Pro for JavaScript.
We are not clear which version is the right one - Web, Saas, OEM.
Our requirement is internal to organization. Please guide.

Comment posted by Shruti Duggal
3 months ago.

Hi,

Any update on this. We want clarity on the different available versions for DayPilot Pro for usage in our project.
We are not clear which version is the right one - Web, Saas, OEM.

Comment posted by Dan Letecky [DayPilot]
3 months ago.

The license type depends on the type of your application:

1. For internal applications used by your employees, you can use the "Web" edition. 

2. If this is for an application that you make available to third parties, the "SaaS" edition is necessary.

3. There is also the "OEM" edition which allows you to include DayPilot in applications that are installed on premises of your customers.

If you need help with choosing the right license, please contact sales@daypilot.org.

This question is more than 3 months old and has been closed. Please create a new question if you have anything to add.