Controllers and callbacks topic
Controllers & Callbacks
This is part of the kalender documentation.
Controllers drive the calendar from your code. Callbacks report back what the user did. Together they are how the calendar connects to the rest of your app.
Controllers
EventsController
EventsController manages and exposes events to the calendar. Typically one instance per app. Use DefaultEventsController unless you need a custom storage layer.
| Method | Description |
|---|---|
addEvent(event) |
Add a single event, returns its String id |
addEvents(events) |
Add multiple events, returns List<String> of ids |
removeEvent(event) |
Remove a specific event |
removeEvents(events) |
Remove a list of events |
removeWhere(test) |
Remove events matching a predicate |
removeById(id) |
Remove the event with the given String id |
updateEvent({event, updatedEvent}) |
Replace an existing event (named parameters) |
replaceEvents(events) |
Replace every stored event with the given list, returns List<String> of ids |
byId(id) |
Return the event with the given String id, or null |
clearEvents() |
Remove all events |
eventsInRange(range) |
Events occurring during the given range (requires the view's multiDayRule, plus optional includeMultiDayEvents, includeDayEvents, and location filters) |
eventsInRange takes a FloatingDateTimeRange, not a KalenderDateTimeRange.
Convert with FloatingDateTimeRange.fromDateTimeRange(range).
KalenderController
KalenderController drives a single KalenderView widget.
State notifiers:
| Notifier | Type | Description |
|---|---|---|
visibleDateTimeRange |
ValueNotifier<KalenderDateTimeRange?> |
The currently visible date range |
visibleTimeOfDay |
ValueNotifier<KalenderTime?> |
Time aligned with the top of the viewport (multi-day views, null otherwise) |
visibleEvents |
ValueNotifier<Set<KalenderEvent>> |
Events visible on screen |
selectedEvent |
ValueNotifier<KalenderEvent?> |
The focused event (shows drop target / resize handles) |
Navigation methods:
jumpToPage(page)/jumpToDate(date)animateToNextPage()/animateToPreviousPage()animateToDate(date)/animateToDateTime(dateTime)animateToEvent(event)
Selection methods: selectEvent(event) focuses an event from code, which is
what draws its drop target and resize handles. deselectEvent() clears it. Both
drive the selectedEvent notifier above.
Internally the controller delegates to a
ViewController(MultiDayViewController,MonthViewController, orScheduleViewController) depending on the activeViewConfiguration.
Disposing
Both controllers hold listeners, so dispose them with the widget that owns them.
class MyCalendar extends StatefulWidget {
const MyCalendar({super.key});
@override
State<MyCalendar> createState() => _MyCalendarState();
}
class _MyCalendarState extends State<MyCalendar> {
final eventsController = DefaultEventsController();
final kalenderController = KalenderController();
@override
void dispose() {
kalenderController.dispose();
eventsController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => const SizedBox.shrink();
}
An EventsController shared across screens belongs to whatever owns it for the
life of the app, and is disposed there rather than in a single screen.
Building the surrounding UI
The calendar draws no toolbar of its own. Switching views, moving between pages
and showing the current month are all built in your app, using the navigation
methods above and a ViewConfiguration held in state.
class CalendarScreen extends StatefulWidget {
const CalendarScreen({super.key});
@override
State<CalendarScreen> createState() => _CalendarScreenState();
}
class _CalendarScreenState extends State<CalendarScreen> {
final eventsController = DefaultEventsController();
final kalenderController = KalenderController();
@override
void dispose() {
kalenderController.dispose();
eventsController.dispose();
super.dispose();
}
late final viewConfigurations = <ViewConfiguration>[
MultiDayViewConfiguration.week(),
MultiDayViewConfiguration.singleDay(),
MonthViewConfiguration.singleMonth(),
];
late ViewConfiguration viewConfiguration = viewConfigurations.first;
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
// The visible range drives the label, so it updates on every scroll,
// page change and view switch.
ValueListenableBuilder(
valueListenable: kalenderController.visibleDateTimeRange,
builder: (context, range, child) {
if (range == null) return const SizedBox.shrink();
return Text('${range.start.monthNameLocalized()} ${range.start.year}');
},
),
IconButton(
onPressed: kalenderController.animateToPreviousPage,
icon: const Icon(Icons.chevron_left),
),
IconButton(
onPressed: kalenderController.animateToNextPage,
icon: const Icon(Icons.chevron_right),
),
IconButton(
onPressed: () => kalenderController.animateToDate(DateTime.now()),
icon: const Icon(Icons.today),
),
const Spacer(),
DropdownButton<ViewConfiguration>(
value: viewConfiguration,
items: [
for (final configuration in viewConfigurations)
DropdownMenuItem(value: configuration, child: Text(configuration.name)),
],
onChanged: (value) {
if (value == null) return;
setState(() => viewConfiguration = value);
},
),
],
),
Expanded(
child: KalenderView(
eventsController: eventsController,
kalenderController: kalenderController,
viewConfiguration: viewConfiguration,
header: KalenderHeader(),
body: KalenderBody(),
),
),
],
);
}
}
Switching viewConfiguration is all a view change takes. What carries over,
such as the date and scroll position, is set on the configuration itself, see
Views.
The basic example has a fuller version of this toolbar.
Callbacks
Pass a KalenderCallbacks to KalenderView to react to user interactions.
KalenderCallbacks(
// --- Event interactions ---
// Called when an event tile is tapped.
onEventTapped: (event) {},
// Called when an event tile is tapped. Includes tap position detail.
// The 'detail' parameter provides the tap location, the tile's 'RenderBox' and
// its exact calculated 'DateTime' position based on the tapped position within
// the event UI.
onEventTappedWithDetail: (event, detail) {},
// Called when an event is secondary tapped (right-clicked).
onEventSecondaryTapped: (event) {},
onEventSecondaryTappedWithDetail: (event, detail) {},
// Called before the calendar creates a new event from a gesture.
// Return your concrete Event subclass here.
onEventCreate: (event) {
return Event(start: event.start,
end: event.end, title: 'New Event');
},
// Same as onEventCreate but includes gesture detail (position, renderBox).
onEventCreateWithDetail: (event, detail) {
return Event(start: event.start,
end: event.end, title: 'New Event');
},
// Called after a new event has been committed. Add it to your controller here.
onEventCreated: (event) => eventsController.addEvent(event),
// Called just before a rescheduled / resized event is applied.
onEventChange: (event) {},
// Called after a rescheduled / resized event is applied.
onEventChanged: (original, updated) {
eventsController.updateEvent(event: original, updatedEvent: updated);
},
// --- Calendar interactions ---
// Called when the visible page changes.
onPageChanged: (visibleDateTimeRange) {},
// Called when the vertical scroll position of a multi-day view changes.
// 'visibleTimeOfDay' is the time aligned with the top of the viewport.
onScrollPositionChanged: (visibleTimeOfDay) {},
// Called when the user taps an empty area (day / week body).
onTapped: (date) {},
onTappedWithDetail: (detail) {
// detail.dateTime or detail.dateTimeRange, plus renderBox & localOffset.
},
// Called when the user secondary taps (right-clicks) an empty area.
onSecondaryTapped: (date) {},
onSecondaryTappedWithDetail: (detail) {},
// Called when the user long-presses an empty area.
onLongPressed: (date) {},
onLongPressedWithDetail: (detail) {},
// Called when the user secondary long-presses an empty area.
onSecondaryLongPressed: (date) {},
onSecondaryLongPressedWithDetail: (detail) {},
// --- Drag-and-drop acceptance ---
// Day / week vertical drag target. Return false to reject the drop.
onWillAcceptWithDetailsVertical: (details, controller, configuration) => true,
// Month / header horizontal drag target.
onWillAcceptWithDetailsHorizontal: (details, controller, configuration) => true,
)
Classes
- ContinuousScheduleViewController Controllers and callbacks
- DayDetail Controllers and callbacks
- The detail for when the calendar is tapped.
- KalenderCallbacks Controllers and callbacks
- The callbacks used by the KalenderView.
- KalenderController Controllers and callbacks
- The KalenderController is used to controller a single KalenderView. It provides some useful functions for navigating the KalenderView.
- KalenderScope Controllers and callbacks
- Reads the state of the KalenderView a widget is built inside.
- MonthViewController Controllers and callbacks
- MultiDayDetail Controllers and callbacks
- The detail for when a multi-day range is tapped.
- MultiDayViewController Controllers and callbacks
- PaginatedScheduleViewController Controllers and callbacks
- ScheduleViewController Controllers and callbacks
- TapDetail Controllers and callbacks
- ViewController Controllers and callbacks
- A controller for calendar views.
Typedefs
- OnEventChange = void Function(KalenderEvent event) Controllers and callbacks
- The callback for when an event is about to be changed.
- OnEventChanged = void Function(KalenderEvent event, KalenderEvent updatedEvent) Controllers and callbacks
- The callback for when an event is changed.
- OnEventCreate = KalenderEvent? Function(KalenderEvent event) Controllers and callbacks
- The call back for creating a new event.
- OnEventCreated = void Function(KalenderEvent event) Controllers and callbacks
- The callback for a new event has been created.
- OnEventCreateWithDetail = KalenderEvent? Function(KalenderEvent event, TapDetail detail) Controllers and callbacks
- The call back for creating a new event with details.
- OnEventTapped = void Function(KalenderEvent event) Controllers and callbacks
- The callback for when an event is tapped.
- OnEventTappedWithDetail = void Function(KalenderEvent event, TapDetail detail) Controllers and callbacks
- The callback for when an event is tapped.
- OnLongPressed = void Function(DateTime date) Controllers and callbacks
- The callback for when a user long presses on an empty space in the calendar.
- OnLongPressedWithDetail = void Function(TapDetail detail) Controllers and callbacks
- The callback for when a user long presses on an empty space in the calendar with details.
- OnPageChanged = void Function(KalenderDateTimeRange dateTimeRange) Controllers and callbacks
- The callback for when a calendar page is changed.
- OnScrollPositionChanged = void Function(KalenderTime visibleTimeOfDay) Controllers and callbacks
- The callback for when the vertical scroll position of a multi-day view changes.
- OnTapped = void Function(DateTime date) Controllers and callbacks
- The callback for when a user taps on an empty space in the calendar.
- OnTappedWithDetail = void Function(TapDetail detail) Controllers and callbacks
- The callback for when a user taps on an empty space in the calendar with details.