FullCalendar’s resource timeline and resource columns are Premium: a commercial app needs a paid license key. Its license page lists the free options, for apps that are entirely AGPL and for registered non-profits. The Needless UI scheduler has both under MIT, with repeating events and iCalendar files. This guide moves an Angular app from one to the other: what carries over, what doesn’t, and the data to convert.
It uses FullCalendar 7’s names, with version 6’s in brackets where they differ. FullCalendar’s Angular connector supports Angular 16 to 22; Needless UI needs Angular 22.
What you get
| Feature | FullCalendar | Needless UI |
|---|---|---|
| Resource timeline: a row per room or person | Premium | Yes: a day, a week or a month |
| Resources as columns in the day and week views | Premium | Yes |
| Month, week and day views | Free | Yes |
| Drag to move and resize | Free; onto another resource with Premium | Yes, onto other resources too. The end resizes, the start doesn’t. |
| Select time to create an event | Free | Yes, with a pointer, a long press or the keyboard |
| Rules such as no overlaps | Free: overlap and constraint options | Yes: one allow function, asked before every change |
| Move and resize events from the keyboard | Not in its accessibility docs, which cover ARIA labels and Tab focus | Yes, announced to screen readers |
| Repeating events | Free, with the rrule plugin and library | Built in: RFC 5545 rules, without EXRULE, RDATE or rules by the hour |
| iCalendar (.ics) | Free: reads a feed | Reads and writes .ics files |
| List and year views | Free | An agenda of the coming days; no year views |
| Time zones | Free: local, UTC or named | No: it shows the wall-clock times it gets |
| Grouped, nested or multi-column resources | Premium | No: one column, drawn by your template |
| External drag and drop, background events | Free | No |
| Printing, virtual rendering | Premium | No |
| Frameworks | Angular 16 to 22, React, Vue, plain JavaScript and more | Angular 22 and React 19 |
What maps to what
| FullCalendar | Needless UI scheduler |
|---|---|
<full-calendar [options]>, plugins, schedulerLicenseKey | <nui-scheduler>, with an input for each option; no plugins and no key |
initialView: 'resourceTimelineDay' | view="timeline", and timelineSpan for a week or a month |
initialView: 'timeGridWeek' | view="week"; [(view)] is two-way |
resources, events | [resources], [events] |
resourceId, extendedProps | resource, data |
editable, selectable | editable, selectable |
select | (slotSelect): { start, end, allDay, resource } |
eventDrop, eventResize | (eventChange): nothing moves until you update events |
eventClick | (eventClick) |
eventOverlap, selectOverlap, eventAllow | [allow]: one function for moves, resizes and selections |
slotDuration, snapDuration | slotMinutes, snapMinutes, in minutes |
slotMinTime, slotMaxTime, scrollTime | dayStart, dayEnd, scrollHour, in hours |
businessHours | [businessHours], with weekdays from 1 (Monday) to 7 |
datesSet | (rangeChange) |
eventContent, resourceCellContent [resourceLabelContent] | nuiSchedulerEvent and nuiSchedulerResource templates |
locale, firstDay | locale (any BCP 47 tag), firstDay from 1 to 7, and labels for its words |
A room booking timeline, both ways
Rooms are resources and bookings are events. People drag across a room to book it and drag a booking to move it, and a room holds one booking at a time. With FullCalendar 7 and its Premium resource timeline:
With the Needless UI scheduler:
Two things work differently. FullCalendar moves a booking itself, and the app copies the change; the Needless UI scheduler only reports it, and updating events keeps it, so your data stays the one source. And allow is plain code, asked before every change from a pointer or the keyboard, so the rule is yours to test. The booking calendar guide builds this app step by step.
Converting the data
| FullCalendar | Needless UI |
|---|---|
An all-day end is the day after the event | An all-day end is its last day: take a day off |
Times may end in Z or an offset such as +02:00 | Wall-clock times without an offset, such as 2026-11-02T09:30 |
Weekdays from 0 (Sunday) to 6, in businessHours and firstDay | Weekdays from 1 (Monday) to 7 (Sunday) |
Durations as strings, such as '00:30' | Numbers: minutes or hours |
| Resources sorted by id, then title | Resources in the order of the array |
rrule as an object, and exrule | An RFC 5545 string, such as FREQ=WEEKLY;BYDAY=MO,FR, and exdate |
A time zone such as America/New_York | Convert the times first. nuiSchedulerFromIcs(text, { timeZone }) converts .ics files as it reads them. |
If you need what’s missing
If your app depends on time zones, grouped resources, external drag and drop or printing, the scheduler can’t replace FullCalendar yet. Open an issue for what you need. For everything else, the scheduler’s page has every input, output and example.