odoo-16

How I can update fullcalendar options from odoo calendar controller


In odoo web module I found CalendarCommonRenderer in his setup method, they get instance of fullcalendar

export class CalendarCommonRenderer extends Component {
    setup() {
        this.fc = useFullCalendar("fullCalendar", this.options);
        this.click = useClickHandler(this.onClick, this.onDblClick);
        this.popover = useCalendarPopover(this.constructor.components.Popover);
        this.onWindowResizeDebounced = useDebounced(this.onWindowResize, 200);

        useEffect(() => {
            this.updateSize();
        });

        useEffect(
            (view) => {
                this.env.config.setDisplayName(`${this.props.displayName} (${view.title})`);
            },
            () => [this.fc.api.view]
        );
    }

and this.options are options for fullcalendar instance parameter, like this:

get options() {
        return {
            allDaySlot: this.props.model.hasAllDaySlot,
            allDayText: this.env._t("All day"),
            columnHeaderFormat: this.env.isSmall
                ? SHORT_SCALE_TO_HEADER_FORMAT[this.props.model.scale]
                : SCALE_TO_HEADER_FORMAT[this.props.model.scale],
            dateClick: this.onDateClick,
            dayRender: this.onDayRender,
            defaultDate: this.props.model.date.toISO(),
            defaultView: SCALE_TO_FC_VIEW[this.props.model.scale],
            dir: localization.direction,
            droppable: true,
            editable: this.props.model.canEdit,
            eventClick: this.onEventClick,
            eventDragStart: this.onEventDragStart,
            eventDrop: this.onEventDrop,
            eventLimit: this.props.model.eventLimit,
            eventLimitClick: this.onEventLimitClick,
            eventMouseEnter: this.onEventMouseEnter,
            eventMouseLeave: this.onEventMouseLeave,
            eventRender: this.onEventRender,
            eventResizableFromStart: true,
            eventResize: this.onEventResize,
            eventResizeStart: this.onEventResizeStart,
            events: (_, successCb) => successCb(this.mapRecordsToEvents()),
            firstDay: this.props.model.firstDayOfWeek % 7,
            header: false,
            height: "parent",
            locale: luxon.Settings.defaultLocale,
            longPressDelay: 500,
            navLinks: false,
            nowIndicator: true,
            plugins: ["dayGrid", "interaction", "timeGrid", "luxon"],
            select: this.onSelect,
            selectAllow: this.isSelectionAllowed,
            selectMinDistance: 5, // needed to not trigger select when click
            selectMirror: true,
            selectable: this.props.model.canCreate,
            slotLabelFormat: is24HourFormat() ? HOUR_FORMATS[24] : HOUR_FORMATS[12],
            snapDuration: { minutes: 15 },
            timeZone: luxon.Settings.defaultZone.name,
            unselectAuto: false,
            weekLabel:
                this.props.model.scale === "month" && this.env.isSmall ? "" : this.env._t("Week"),
            weekNumberCalculation: "ISO",
            weekNumbers: true,
            weekNumbersWithinDays: !this.env.isSmall,
            windowResize: this.onWindowResizeDebounced,
        };
    }

and CalendarCommonRenderer is a subcomponent of CalendarRenderer to determine if is week, day calendar. In registry they add calendarView, like bellow:

export const calendarView = {
    type: "calendar",

    display_name: "Calendar",
    icon: "fa fa-calendar",
    multiRecord: true,
    searchMenuTypes: ["filter", "favorite"],

    ArchParser: CalendarArchParser,
    Controller: CalendarController,
    Model: CalendarModel,
    Renderer: CalendarRenderer,

    buttonTemplate: "web.CalendarController.controlButtons",

    props: (props, view) => {
        const { ArchParser } = view;
        const { arch, relatedModels, resModel } = props;
        const archInfo = new ArchParser().parse(arch, relatedModels, resModel);
        return {
            ...props,
            Model: view.Model,
            Renderer: view.Renderer,
            buttonTemplate: view.buttonTemplate,
            archInfo,
        };
    },
};

registry.category("views").add("calendar", calendarView);

Now, I want to update from CalendarController the fullcalendar options or re.render the fullcalendar with new options.

ATT.: in my code I have inhertance for CalendarController, CalendarModel, CalendarRenderer and CalendarCommonRenderer

I can Update fullcalendar options or re-render with new options from CalendarModel, CalendarRenderer or CalendarController?


Solution

  • You can fix from CalendarModel component. CalendarCommonRender and CalendarController they share CalendarModel instance.

    Go to CalendarModel (inheritance) and create a new setter and getter:

    In your setup() override add:

    this.fc_api = null;
    

    Create setter and getter:

    set fcApi(api){
      this.fc_api = api;
    }
    get fcApi(){
     return this.fc_api;
    }
    

    Now, in your CalendarCommonRender (inheritance) component add in setup() override:

    mounted( () =>{
      this.props.model.fcApi(this.fc);
    })
    

    Go to CalendarController (inheritance) component override

    Where you need call (in my case I am calling in setup() override):

    mounted( ()=>{
      this.midel.fcApi.setOption("minTime": "09:00:00");
    });
    

    Now you can update fullcalendar option where you need in CalendarController, but only after component completely mounted