[v7] TimeGrid loses its time axis and row heights when `slotMinTime` is moved later via `setOption` on a mounted view
Reduced Test Case
https://codepen.io/editor/david-mcgurrin/pen/01a08bd0-4288-734d-8936-adf7a21bb3e2
Do you understand that if a reduced test case is not provided, we will intentionally delay triaging of your ticket?
- I understand
Which connector are you using (React/Angular/etc)?
No connector (vanilla JS)
Bug Description
Moving slotMinTime later on an already-rendered TimeGrid (plain timeGridDay or resourceTimeGridDay) drops every slot row to its natural height, ignoring slotMinHeight, and the time axis loses all of its labels and collapses to zero width. With the classic theme in the pen the rows go from 40px to about 17px with no axis; with a flatter theme (our production app) they go to about 5px, the whole grid is squashed into a strip under the resource headers and the body looks blank.
It only happens when the new slotMinTime is later and sits at a different offset within the label interval, so the set of labelled slats changes. From a rendered 05:45 start with 15-minute slots (labels every 30 minutes, on :15 and :45):
setOption("slotMinTime", …) |
Direction | Label phase | Result |
|---|---|---|---|
06:45, 07:45 |
later | unchanged (:45) | fine |
06:00, 07:00, 08:00 |
later | shifts to :00 | rows collapse |
05:15 |
earlier | unchanged | fine |
05:00, 04:30 |
earlier | shifts | fine |
05:45 |
same | same | fine |
Moving slotMaxTime in either direction is always fine.
It also needs unlabelled (minor) slats to exist: with slotDuration: "00:15" and the default 30-minute label interval it reproduces every time; with slotDuration: "00:30", where every slat carries a label, the same slotMinTime changes render correctly.
The broken state is sticky. None of the following recover it:
calendar.render()- dispatching a
resizeevent onwindow setOptiononslotDuration,slotLabelInterval,slotMinHeight,heightorexpandRowschangeViewto the same view typebatchRenderingaround a change to another view and back
Only a real remount recovers it: changeView to a different view and back (two separate calls), or destroy() followed by render().
What appears to happen internally
I instrumented computeSlatHeight and handleSlatInnerHeights in the TimeGrid layout to log their inputs.
Healthy render, then setOption("slotMinTime", "08:00"):
computeSlatHeight { expandRows: false, slatCnt: 65, explicitSlatMinHeight: 40, slatInnerHeight: 12.578, scrollerHeight: 854 }
computeSlatHeight { expandRows: false, slatCnt: 56, explicitSlatMinHeight: 40, slatInnerHeight: 12.578, scrollerHeight: 854 }
handleSlatInnerHeights { size: 14, max: 12.578, vals: [12.578, 12.578, 12.578, 12.578] }
handleSlatInnerHeights { size: 14, max: 0, vals: [0, 0, 0, 0] } <-- labels re-reported as 0
computeSlatHeight { expandRows: false, slatCnt: 56, explicitSlatMinHeight: 40, slatInnerHeight: 0, scrollerHeight: 854 }Once slatInnerHeight is 0, computeSlatHeight returns [null, false] (the !slatInnerHeight early return), so no explicit height is written to the slat header cells or lanes and they collapse. In the collapsed DOM the axis scroller is 0px wide, the slat header cells are 14px x 0px with an empty style attribute, and the label inner elements never report a non-zero height again, so the state never self-corrects.
The same sequence with setOption("slotMaxTime", "18:00") keeps slatInnerHeight at 12.578 and renders correctly, so it is specifically the removal of leading slatMetas that leaves the label height map full of zeros.
Expected behaviour
Changing slotMinTime at runtime re-renders the grid with the new range and the same row heights, as changing slotMaxTime does.
Actual behaviour
The axis empties and every row loses its height; the grid is unusable until the view is remounted.
Environment
fullcalendar/fullcalendar-scheduler7.0.0 (reproduced on 7.1.0 as well)- Chrome 152 on macOS 15.6, also seen in production by end users
- Options in use:
resourceTimeGridDay,slotDuration: "00:15",slotMinHeight: 40,allDaySlot: false,dayMinWidth: 200,expandRows: false
Real-world trigger
A venue booking calendar derives slotMinTime / slotMaxTime from the opening hours of the day being viewed and applies them with setOption after the resources for that day load. Any day that opens later than the day previously viewed (a holiday schedule, for example) moves slotMinTime later and blanks the calendar. Our current workaround is to never move slotMinTime later on a mounted view.
Source: fullcalendar/fullcalendar