2

Currently setting up FullCalendar using ReactJS. I can populate my calendar and the events but having trouble with the eventClick={}. How can I populate a modal using eventClick={} and retrieve event information?

I have managed to get the modal to appear when the event is clicked on but I cannot seem to pass any data through < this is the closest I got. I thought of perhaps greating a function where the modal fires off but I cant work out how to make it show.

Current Code

constructor() {
        super();
        this.state = {
            modal: false
        };

        this.toggle = this.toggle.bind(this);
    };

    toggle() {
        this.setState(prevState => ({
            modal: !prevState.modal
        }));
    }

----
  //I then render the calendar and modal inside the div.

<div id="calendar" class="container" ref="calendar">
                <FullCalendar
                    header={{
                        left: 'prev,next today',
                        center: 'title',
                        right: 'dayGridMonth, listWeek'
                    }}
                    selectable={true}
                    height={650}
                    aspectRatio={2}
                    plugins={[interaction, dayListPlugin, dayGridPlugin, bootstrapPlugin]}
                    themeSystem="bootstrap"
                    weekends={false}
                    displayEventTime={true}
                    timeZone="UTC"
                    events={jsonFeed}
                    eventRender={this.handleEventRender}
                    eventClick={this.toggle}
                />
            <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
            <ModalHeader toggle={this.toggle}>testTitle</ModalHeader>
            <ModalBody>test body</ModalBody>
            <ModalFooter>
                <Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
                <Button color="secondary" onClick={this.toggle}>Cancel</Button>
            </ModalFooter>
        </Modal>
            </div>

So here I get the modal appearing and disappearing when I click on the event/close button but I cannot pass the data from the event clicked through it. I hope that someone can help. I cant seem to get it to do it.

ADyson
  • 57,178
  • 14
  • 51
  • 63
  • Are you perhaps using this? https://fullcalendar.io/docs/react . If so then maybe you meant to say "ReactJS" instead of "NodeJS" in your question?? – ADyson May 23 '19 at 11:06
  • @ADyson I am indeed using React, I had node on the brain from another project. Woops –  May 23 '19 at 11:16
  • No problem. Ok, so the "Callbacks" section of the link I gave you explains how to handle a callback such as eventClick. I suggest you handle that via function you can define, and use that to toggle your modal, and also populate the modal with the event data (which is supplied as an argument to the callback - see https://fullcalendar.io/docs/eventClick). – ADyson May 23 '19 at 11:22
  • @ADyson thanks, do you know how I would render it? So I have changed it to be in a function but I just cant figure what to write to render it? ReactDOM? but then I dont know what I need to pass it to get it to show. –  May 23 '19 at 14:49
  • Sorry I'm not a React expert at all, never used it, but I'm just telling you from the fullCalendar point of view. In regular JavaScript you'd issue a command to make something show on screen, presumably React has some similar procedure. Maybe if you edit your question to show what you've written up to now, I might be able to figure it out a bit better. – ADyson May 23 '19 at 15:18
  • Sorry having read through this again I don't think my answer helps, am I right in thinking that the Modal displays and you can actually access the event object now but you are unsure how to get those values into the Modal? Have you created the Modal yourself or are you using a library? – Ally Murray May 24 '19 at 08:08
  • @ADyson I have managed to get it to pass through the data and appear on event click. My trouble is now getting it to close. https://codesandbox.io/s/modern-forest-hvs5h?fontsize=14 btw can I just say I appreciate the help! Im new to react & fullcalendar. –  May 24 '19 at 11:56
  • @AllyMurray Yes that was my problem, using a library. I have managed to get it to pass through the data and appear on event click. My trouble is now getting it to close. heres my sandbox codesandbox.io/s/modern-forest-hvs5h?fontsize=14 –  May 24 '19 at 11:57
  • I don't know if it's just me but the display on that codepen is all screwed up, the calendar is a mess, and clicking on events (at least I think that's what I'm doing, it's hard to tell!) just produces some console logs, not a modal. Any chance you could make it usable? – ADyson May 24 '19 at 12:46
  • @ADyson yeah the calendar is a mess for whatever reason (perhaps something to do with codepen?) but if you click on event1 its producing a modal for me. The link again just to confirm https://codesandbox.io/s/modern-forest-hvs5h?fontsize=14 –  May 24 '19 at 12:56
  • Ok I see. I think I was clicking inaccurately before. I think the closing of the modal is more of a bootstrap issue than fullCalendar, and I wouldn't know how to configure that in react, so sorry I can't be of more help there. – ADyson May 24 '19 at 13:13
  • @Dean I have updated your Code Sandbox and my answer. – Ally Murray May 24 '19 at 15:46

2 Answers2

1

Your question states "So here I get the modal appearing and disappearing when I click on the event/close button..." but in the comments you state "but I just can't figure what to write to render it".

I am going to assume the Modal is being rendered and that the issue is you are unsure how to use the eventClick callback.

ADyson was spot on about the issue you are having. You have already set up the callback, FullCalendar considers your toggle function the function to call when it triggers the event click. When your toggle function is called it will be passed an eventClickInfo object that gives you access to the event, HTML element, jsEvent and the view.

So changing your toggle to this would give you access to the event:

toggle(eventClickInfo) {
  console.log(eventClickInfo);

  this.setState(prevState => ({
    modal: !prevState.modal
  }));
}

*I would change the name to handleEventClick or eventClick.

Update 1: Based on the comments above I have taken your code sandbox and updated. I changed the following:

  1. Moved the modal into the render function so that it's rendered then updated from the state.
  2. Added the event to the state object so when you click the event this is updated. This is then what is rendered in the dialog.
  3. Changed class to className on the div with the id calendar since this is standard in React due to class being a keyword in JS.

    class Calendar extends React.Component {
      state = {
        modal: false,
        event: {
          title: "",
          start: new Date()
        }
      };
    
      toggle = () => {
        this.setState({ modal: !this.state.modal });
      };
    
      handleEventClick = ({ event, el }) => {
        this.toggle();
        this.setState({ event });
      };
    
      render() {
        return (
          <div id="calendar" className="container" ref="calendar">
            <FullCalendar
              header={{
                left: "prev,next today",
                center: "title",
                right: "dayGridMonth, listWeek"
              }}
              selectable={true}
              plugins={[interaction, dayListPlugin, dayGridPlugin, bootstrapPlugin]}
              themeSystem="bootstrap"
              weekends={false}
              displayEventTime={true}
              timeZone="UTC"
              events={[
                { title: "event 1", date: "2019-05-01" },
                { title: "event 2", date: "2019-05-02" }
              ]}
              eventRender={this.handleEventRender}
              eventClick={this.handleEventClick}
            />
            <Modal
              isOpen={this.state.modal}
              toggle={this.toggle}
              className={this.props.className}
            >
              <ModalHeader toggle={this.toggle}>
                {this.state.event.title}
              </ModalHeader>
              <ModalBody>
                <div>
                  <p>{this.state.event.start.toISOString()}</p>
                </div>
              </ModalBody>
              <ModalFooter>
                <Button color="primary">Do Something</Button>{" "}
                <Button color="secondary" onClick={this.toggle}>
                  Cancel
                </Button>
              </ModalFooter>
            </Modal>
          </div>
        );
      }
    }
    
Ally Murray
  • 599
  • 1
  • 6
  • 16
  • Thank you so much, this is really helpful! I was starting to pull my hair out. Not only did you give me a solution but an explanation :) Have a great monday. –  May 27 '19 at 07:16
  • You're welcome, just remember that you will have to add any other properties you care about to the event object in your local state. – Ally Murray May 27 '19 at 07:57
  • Yes - do you know how I would pass through something like an extendedProp? I am having issues getting that but am able to get every other piece of info from the event. –  May 27 '19 at 08:48
  • extendedProp is an object itself so you are looking at nested state. Have a look at this: https://stackoverflow.com/a/43041334/3891834 – Ally Murray May 27 '19 at 08:51
  • Thanks so so much –  May 27 '19 at 09:01
0

on your button(styled-components),

<Button type="button" color="primary" onClick={e => toggle(e)}>Toggle Button</Button>

also on your handleToggle()

toggle = event => {
 // event.preventDefault() or manipulate something with the @param
 this.setState(prevState => ({ modal: !prevState.modal }))
}
pope_maverick
  • 902
  • 8
  • 15