fullcalendar rendering multiple calenders on one page, only last calendar refreshes when dateClick or select is fired

227 Views Asked by At

I have fullcalendar 4.3.1 working properly when only 1 calendar is on the page, however when I put 3 calendars on the page, only the last one refreshes properly when clicking a date or drag selecting several dates. I have to click the refresh button to get the first or second calendars to refresh.

Here is a video demonstrating the issue... calendar-refresh-issue.mov

I am assigning a unique id to each calendar using the data-id and a custom attribute...

data-id="calendar-3"
calendar-id="calendar-3"

Here is the init method that fires for each calendar loaded...

init() {
var calendarEl = this.template.querySelector(`[data-id="${this.calendarId}"]`); 
// eslint-disable-next-line no-undef
this.calendar = new FullCalendar.Calendar(calendarEl, {
  plugins: ["dayGrid", "timeGrid", "list","interaction","moment"],
  views: {
    listDay: { buttonText: "list day" },
    listWeek: { buttonText: "list week" },
    listMonth: { buttonText: "list month" },
    timeGridWeek: { buttonText: "week time" },
    timeGridDay: { buttonText: "day time" },
    dayGridMonth: { buttonText: "month", eventLimit:4 },
    dayGridWeek: { buttonText: "week" },
    dayGridDay: { buttonText: "day" }
  },
  
  eventRender: info => {
    if (info.view.type === 'listMonth') {return}
  
    let eventEl = info.el.querySelector('.fc-content');
    let eventID = info.event.id;
    let link = document.createElement('a');
    let linkIcon = document.createElement('i');
  
    link.id = eventID;

    let colors = {
      backgroundColor: info.event.backgroundColor,
      borderColor: info.event.borderColor,
      textColor: info.event.textColor
    }

    if(self.colorState === false) {
      colors.backgroundColor = '#fff';
      colors.borderColor = '#000';
      colors.textColor = '#000';
    }

    if(info.event.extendedProps.status === 'Confirmed') {
      linkIcon.classList.add('float-right', 'fa', 'fa-thumbs-up');
      linkIcon.style.color = colors.textColor;
      linkIcon.style.paddingRight = '3px';
      linkIcon.style.fontSize = 'medium';
    }
    else if(info.event.extendedProps.status === 'Unconfirmed') {
      linkIcon.classList.add('float-right', 'fa', 'fa-thumbs-o-up');
      linkIcon.style.color = colors.textColor;
      linkIcon.style.paddingRight = '3px';
      linkIcon.style.fontSize = 'medium';
    }

    eventEl.style.padding = '3px';
    eventEl.style.backgroundColor = colors.backgroundColor;
    eventEl.style.color = colors.textColor;
    eventEl.style.borderColor = colors.borderColor;

  
   link.appendChild(linkIcon);
   eventEl.insertBefore(link, eventEl.children[0]);
  },

  eventClick: info => {
    if(this.mode !== 'Confirmation' 
      || (this.shift === 'Available' 
          && info.event.extendedProps.status === 'Availability'
          && info.event.extendedProps.providerId === this.providerId)) {
      removeEvent({id: info.event.id}).then(result => {
        if(result) {
          info.event.remove();
        }
        else {
          this.dispatchEvent(
            new ShowToastEvent({
              title: "Remove Shift Failed",
              message: "Unable to remove event " + info.event.id,
              variant: "error"
            })
          )
        }
      });
    }
    else {
      let evt = {
        eventId: info.event.id,
        whoId: info.event.extendedProps.whoId,
        whatId: info.event.extendedProps.whatId,
        providerId: (this.shift === 'Claim' ? this.providerId : info.event.extendedProps.providerId),
        status: 'Confirmed',
        shift: info.event.extendedProps.shift,
        title: (this.shift === 'Claim' ? this.title : info.event.title),
        start: info.event.start,
        end: info.event.end,
        backgroundColor: '#006600',
        borderColor: '#006600',
        textColor: '#ffffff'
      }

      saveEvent({eventId: evt.eventId, whoId: evt.whoId, whatId: evt.whatId, providerId: evt.providerId, title: evt.title, startTime: evt.start, endTime: evt.end, allDayEvent: false, colorValue: evt.backgroundColor, borderColorValue: evt.borderColor, textColorValue: evt.textColor, status: evt.status, shift: evt.shift})
      .then(result => {
        if(result && result.error) {
          console.log(result.error);
        }
      });          
    }
  },

  eventMouseEnter: info => {console.log("mouse enter", info)},

  select: function(info) {
    let allDayEvent = false;
    let startDate, endDate;

    if(self.mode === 'Scheduling' || self.shift === 'Available') {
      console.log('selected ' + info.startStr + ' to ' + info.endStr);
      if(!self.startTime || self.startTime === null){
        allDayEvent = true;
        startDate = new Date(info.startStr + 'T00:00:00');
        endDate = new Date(info.endStr + 'T00:00:00');
      }
      else {
        startDate = new Date(info.startStr + 'T' + self.startTime);
        endDate = new Date(info.endStr + 'T' + self.endTime);
        endDate = endDate.setDate(endDate.getDate() - 1);
      }

      
      for (let d = startDate; d < endDate; d.setDate(d.getDate() + 1)) {
        let sd = d.toISOString();
        let ed = sd.substring(0,10) + 'T' + (allDayEvent ? '00:00:00' : self.endTime);

        self.createEvent(new Date(d), new Date(ed), allDayEvent);
      }
    }
  },

  dateClick:info => {
    if(this.mode === 'Scheduling' || this.shift === 'Available') {
      console.log("date click", info);

      let allDayEvent = false;
      let startDate, endDate;

      if(!self.startTime || self.startTime === null){
        allDayEvent = true;
        startDate = new Date(info.dateStr + 'T00:00:00');
        endDate = new Date(info.dateStr + 'T00:00:00');
      }
      else {
        startDate = new Date(info.dateStr + 'T' + self.startTime);
        endDate = new Date(info.dateStr + 'T' + self.endTime);
      }

      self.createEvent(startDate, endDate, allDayEvent);
    }
  },

  eventReceive: info => {
    let evt = {
      eventId: info.event.id,
      whoId: info.event.extendedProps.whoId,
      whatId: info.event.extendedProps.whatId,
      providerId: info.event.extendedProps.providerId,
      status: info.event.extendedProps.status,
      shift: info.event.extendedProps.shift,
      title: info.event.title,
      start: info.event.start,
      end: info.event.end,
      textColor: info.event.textColor,
      backgroundColor: info.event.backgroundColor,
      borderColor: info.event.borderColor
    }

    saveEvent({eventId: evt.eventId, whoId: evt.whoId, whatId: evt.whatId, providerId: evt.providerId, title: evt.title, startTime: evt.start, endTime: evt.end, allDayEvent: false, colorValue: evt.backgroundColor, borderColorValue: evt.borderColor, textColorValue: evt.textColor, status: evt.status, shift: evt.shift})
    .then(result => {
      if(result && result.error) {
        console.log(result.error);
      }
    });

  },

  selectable: true,
  selectMinDistance: 200,
  height: this.height,
  aspectRatio: this.aspectRatio,
  defaultDate: this.defaultDate,
  eventLimit: true,
  editable: true,
  droppable: true,
  showNonCurrentDates: false,
  header: false,

  eventSources: [
    {
      events: this.eventSourceHandler,
      id: `custom-${this.calendarId}`
    },
  ],
});
this.calendar.render();
this.calendarLabel = this.calendar.view.title;

}

The refresh button logic is simple...

  @api refresh() {
      var eventSource = this.calendar.getEventSourceById(`custom-${this.calendarId}`);
      eventSource.refetch();
  }

I am using this in a series of salesforce lightning web components, but I don't believe this information is a factor since the calendar does work properly when only one is on the page.

0

There are 0 best solutions below