I had a syncfusion calendar custom widget working in my code before the lastest update that was on January 29th, 2025. Now in test mode will not run, and I get an "Build Failed" with no error.
Syncfusion Calendar, Build Failed - No errors, was working before update.
Custom Code
I've tried changing the package version to a lot of different ones to see if that was the case but nothing has worked. I've even tried cutting out certain parts of the code to eliminate different possible problems but no success. This Calendar is a key part of my app and I need to work to continue.
Here is my current code. With database requests stripped out.
import 'package:syncfusion_flutter_calendar/calendar.dart';
class Calendar extends StatefulWidget {
const Calendar({
super.key,
this.width,
this.height,
required this.onAppointmentTapped,
required this.onCalendarTapped,
});
final double? width;
final double? height;
final Future<dynamic> Function(Map<String, dynamic>) onAppointmentTapped;
final Future<dynamic> Function(Map<String, dynamic>) onCalendarTapped;
@override
State<Calendar> createState() => _CalendarState();
}
class _CalendarState extends State<Calendar> {
late MeetingDataSource _flightLogs;
List<Meeting> _meetings = [];
List<CalendarResource> _resources = [];
bool _isLoading = true;
late CalendarController _calendarController;
@override
void initState() {
super.initState();
_calendarController = CalendarController();
_loadTestData();
}
@override
void dispose() {
_calendarController.dispose();
super.dispose();
}
void _loadTestData() {
// Create test resources (aircraft)
_resources = [
CalendarResource(
id: '1',
displayName: 'N12345 - C172',
color: Colors.blue,
),
CalendarResource(
id: '2',
displayName: 'N67890 - PA28',
color: Colors.green,
),
CalendarResource(
id: '3',
displayName: 'N11223 - C152',
color: Colors.orange,
),
CalendarResource(
id: '3',
displayName: 'N11223 - C152',
color: Colors.orange,
),
CalendarResource(
id: '3',
displayName: 'N11223 - C152',
color: Colors.orange,
),
CalendarResource(
id: '3',
displayName: 'Steven',
color: Colors.orange,
),
CalendarResource(
id: '3',
displayName: 'Alex Smith',
color: Colors.orange,
),
CalendarResource(
id: '3',
displayName: 'Meeting Room 1',
color: Colors.orange,
),
];
// Create test meetings (flights)
final now = DateTime.now();
_meetings = [
Meeting(
'John Smith - Training',
DateTime(now.year, now.month, now.day, 9, 0),
DateTime(now.year, now.month, now.day, 11, 0),
Colors.blue,
false,
resourceIds: ['1'],
),
Meeting(
'Sarah Johnson - Check Ride',
DateTime(now.year, now.month, now.day, 13, 0),
DateTime(now.year, now.month, now.day, 15, 0),
Colors.green,
false,
resourceIds: ['2'],
),
Meeting(
'Mike Davis - Solo',
DateTime(now.year, now.month, now.day, 10, 0),
DateTime(now.year, now.month, now.day, 12, 0),
Colors.orange,
false,
resourceIds: ['3'],
),
];
setState(() {
_flightLogs = MeetingDataSource(_meetings);
_flightLogs.resources = _resources;
_isLoading = false;
});
}
Future<void> _handleCalendarTapped(CalendarTapDetails details) async {
if (details.targetElement == CalendarElement.calendarCell) {
// Handle tap on empty calendar cell
final Map<String, dynamic> params = {
'tappedDate': details.date?.millisecondsSinceEpoch,
'resourceId': details.resource?.id,
'resourceName': details.resource?.displayName,
};
await widget.onCalendarTapped(params);
} else if (details.targetElement == CalendarElement.appointment) {
// Handle tap on existing appointment
final Meeting tappedMeeting = details.appointments?[0] as Meeting;
final Map<String, dynamic> params = {
'eventName': tappedMeeting.eventName,
'startTime': tappedMeeting.from.millisecondsSinceEpoch,
'endTime': tappedMeeting.to.millisecondsSinceEpoch,
'resourceIds': tappedMeeting.resourceIds,
'isAllDay': tappedMeeting.isAllDay,
};
await widget.onAppointmentTapped(params);
}
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return Container(
width: widget.width,
height: widget.height,
child: const Center(
child: CircularProgressIndicator(),
),
);
}
final screenWidth = MediaQuery.of(context).size.width;
final isMobile = screenWidth < 600;
return Container(
width: widget.width,
height: widget.height,
child: SfCalendar(
controller: _calendarController,
view: CalendarView.timelineDay,
dataSource: _flightLogs,
showDatePickerButton: true,
showTodayButton: true,
showNavigationArrow: true,
onTap: _handleCalendarTapped,
timeSlotViewSettings: TimeSlotViewSettings(
startHour: 6,
endHour: 22,
nonWorkingDays: const <int>[],
timeFormat: 'HH:mm',
timeIntervalHeight: -1,
timeIntervalWidth: isMobile ? 45 : -1,
),
resourceViewSettings: ResourceViewSettings(
visibleResourceCount: 12,
showAvatar: false,
displayNameTextStyle: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
),
size: isMobile ? 80 : 100,
),
viewNavigationMode: ViewNavigationMode.snap,
allowedViews: const [
CalendarView.timelineDay,
CalendarView.timelineWeek,
CalendarView.timelineWorkWeek,
],
),
);
}
}
class MeetingDataSource extends CalendarDataSource {
MeetingDataSource(List<Meeting> source) {
appointments = source;
}
@override
DateTime getStartTime(int index) {
return appointments![index].from;
}
@override
DateTime getEndTime(int index) {
return appointments![index].to;
}
@override
String getSubject(int index) {
return appointments![index].eventName;
}
@override
Color getColor(int index) {
return appointments![index].background;
}
@override
List<Object>? getResourceIds(int index) {
return (appointments![index] as Meeting).resourceIds;
}
@override
bool isAllDay(int index) {
return appointments![index].isAllDay;
}
}
class Meeting {
Meeting(
this.eventName,
this.from,
this.to,
this.background,
this.isAllDay, {
this.resourceIds,
});
String eventName;
DateTime from;
DateTime to;
Color background;
bool isAllDay;
List<Object>? resourceIds;
}
Yes
3