Search code examples
javagwtfullcalendardomino-uinalu

FullCalendar in GWT : How to refresh calendar while keeping events


I'm working on a GWT application using Domino/UI, Nalukit and the Javascript plugin FullCalendar v6. I made a custom popup to modify and delete an event but when I validate the form, my calendar refreshes and all the event in my week view disappear.

Demo of the app running

I used the native function gotoDate to change to view of the calendar to the event's modified date.

Here's a sample from my controller's render and refreshCalendar methods :

    @Override
    public void render() {

        // Styling related lines omitted

        FcOptionOverrides mainOptions = new FcOptionOverrides();
        mainOptions.locale = "fr";
        mainOptions.initialView = "timeGridWeek";
        mainOptions.views = new FcViewOptions();
        mainOptions.views.timeGridWeek = new FcView();
        mainOptions.views.timeGridWeek.weekends = true;
        mainOptions.views.timeGridWeek.slotMinTime = "07:00:00";
        mainOptions.views.timeGridWeek.slotMaxTime = "22:00:00";
        mainOptions.eventSources = new FcEventSources();
        mainOptions.eventSources.events = this.getController()::onEventNeedMain;
        mainOptions.datesSet = this::onDatesSet;
        
        mainOptions.eventDidMount = this::onEventDidMount;
        mainOptions.dateClick = this::onBigCalendarDateClick;

        mainCalendar = new FcCalendar(mainAgendaContainer, mainOptions);

        FcOptionOverrides smallOptions = new FcOptionOverrides();
        smallOptions.locale = "fr";
        smallOptions.initialView = "dayGridMonth";
        smallOptions.height = "330px";
        smallOptions.aspectRatio = 1.0f;
        smallOptions.eventSources = new FcEventSources();
        smallOptions.eventSources.events = this.getController()::onEventNeedSmall;

        smallOptions.dateClick = this::onSmallCalendarDateClick;

        smallCalendar = new FcCalendar(smallAgendaContainer, smallOptions);

        // radio button for displaying week-ends
        RayflexRadio displayWeekendRadio = new RayflexRadio("weekends", "Week-ends", "Afficher", "Masquer");
        displayWeekendRadio.style("position:absolute; top:18px; right:230px;");
        displayWeekendRadio.addChangeHandler(event -> {

            if (displayWeekendRadio.getValue()) {

                DominoElement.of(mainAgendaContainer).removeCss(RxResource.INSTANCE.gss().calendar_main_no_weekends());
                DominoElement.of(mainAgendaContainer).css(RxResource.INSTANCE.gss().calendar_main());

            } else {

                DominoElement.of(mainAgendaContainer).removeCss(RxResource.INSTANCE.gss().calendar_main());
                DominoElement.of(mainAgendaContainer).css(RxResource.INSTANCE.gss().calendar_main_no_weekends());

            }
            displayWeekEnds = displayWeekendRadio.getValue();
            refreshCalendar();

        });

        displayWeekendRadio.setValue(displayWeekEnds);

        card.getBody().appendChild(displayWeekendRadio.element());

        initElement(card.element());
    }

 @Override
    public void refreshCalendar() {

        if (lastModifiedEvent != null) {
            
            Date beginDate = lastModifiedEvent.getBeginDate();
            JsDate jsDate = new JsDate(1900 + beginDate.getYear(), beginDate.getMonth(), beginDate.getDate());

            mainCalendar.gotoDate(jsDate);
            smallCalendar.gotoDate(jsDate);
        }
        
        mainCalendar.refetchEvents();
    }

Here's my wrapper class for FullCalendar's JS functions :

package com.alara.rayflex.ui.client.calendar;

import elemental2.core.JsDate;
import elemental2.dom.Element;
import jsinterop.annotations.JsType;

@JsType(isNative = true, namespace = "FullCalendar", name="Calendar")
public class FcCalendar {

    public FcCalendar(Element root) {}
    
    public FcCalendar(Element root, FcOptionOverrides optionOverrides) {}
    
    public native void render();
    public native void updateSize();
    
    public native void gotoDate(JsDate start);
    public native JsDate getDate();
    
    public native void setOption(String name, String value);
    public native void setOption(String name, int value);
    
    public native void select(JsDate date);
    
    public native void refetchEvents();
    
    public native void addEventSource(FcOnEventNeed needEvent);
    
    public native void changeView(String viewName, JsDate dateOrRange);
}

I tried to force the native javascript functions refetchEvents with gotoDate but I got the same result. Then I tried using addEventSource to restore my events but still no success there.

I'm expecting to rerender my calendar with the events of the week which the event has been modified.


Solution

  • Solved my issue by loading the events in a callback and refetching them in my refreshCalendar method :

    @Override
    public void refreshCalendar() {
    
        if (lastModifiedEvent != null)
            
            moveToLastEventModifiedDate();
    
        else
        
            mainCalendar.refetchEvents();         
    }
    
    /**
     * Use the last modified event to move the calendar to its begin date
     * then fetch the events to load them again in the calendar component 
     */
    public void moveToLastEventModifiedDate() {
        
        Date eventDate = lastModifiedEvent.getBeginDate();
        JsDate jsEventDate = new JsDate(1900 + eventDate.getYear(), eventDate.getMonth(), eventDate.getDate());
        
        Date previousMonday = DateUtils.getPreviousMonday(eventDate);
        Date nextMonday = DateUtils.getNextMonday(eventDate);
    
        JsDate jsDateBegin = new JsDate(1900 + previousMonday.getYear(), previousMonday.getMonth(), previousMonday.getDate());
        JsDate jsDateEnd = new JsDate(1900 + nextMonday.getYear(), nextMonday.getMonth(), nextMonday.getDate());
    
        mainCalendar.gotoDate(jsEventDate);
        smallCalendar.select(jsEventDate);
    
        FcEventFetchInfo info = new FcEventFetchInfo();
        info.start = jsDateBegin;
        info.end = jsDateEnd;
        
        this.getController().onEventNeedMain(info, success -> {
            mainCalendar.setOption("events", fcOnEventNeed);
            mainCalendar.refetchEvents();
            
        }, failure -> {
            
            ErrorManager.displayServerError("event.list", failure.message, getController().getEventBus());
        });
    
        lastModifiedEvent = null;
    }