[SOLVED] Not showing recurring events in SfCalendar

Hi,

I have developed an android app with flutter where I have a SfCalendar. I'm loading events in SfCalendar from Google Calendar. It shows all events correctly but it doesn't show recurrecy events. It only shows the first event of a recurrency events. What can I do to show recurrency events from Google to SfCalendar?

Thanks.

6 Replies 1 reply marked as answer

IR Indumathi Ravichandran Syncfusion Team April 7, 2021 11:26 AM UTC

Hi nestor, 
 
Thank you for contacting Syncfusion support. 
 
Based on the provided information, we have checked “Flutter calendar doesn’t show the recurrence events from google calendar properly” and we are able to replicate the issue. If possible, can you please share the below details with us. 
 
·       Code snippet for loading the google calendar recurrence events to Syncfusion Calendar. 
 
Also, we have a KB sample for loading google calendar events. If possible, can you please modify the below sample based on your requirement? 
 
KB link: 
 
Sample link: 
 
It would be helpful for us to analyze and provide you a solution at the earliest. 
 
Regards, 
Indumathi R 


Marked as answer

NE nestor April 7, 2021 04:43 PM UTC

Thanks for replying. The code snippet are the following:

Code to load the SfCalendar:
return Container(
child: Stack(
children: [
Container(
child: SfCalendar(
// cellEndPadding: 5,
view: CalendarView.month,
showNavigationArrow: true,
firstDayOfWeek: DateTime.monday,
dataSource: GoogleDataSource(events: snapshot.data),
monthViewSettings: MonthViewSettings(
appointmentDisplayMode:
MonthAppointmentDisplayMode.appointment,
showAgenda: true,
agendaViewHeight: sizeScreen.height*0.25,
),
),
),
snapshot.data != null ? Container() : Center(
child: CircularProgressIndicator(),
)
],
)
);
Code for loading Events from 2 Google Calendars:

Future<List<GoogleCalendar.Event>> getGoogleEventsData(String idCalendar) async {
// TODO: PASAR ÉSTO AL LOGIN PARA NO HACER DOBLE SIGNIN O SERIALIZAR EL SIGNIN
// inal GoogleSignIn googleSignIn = new GoogleSignIn();
final GoogleSignInAccount googleUser = await _googleSignIn.signInSilently(); // De esta forma no aparece la ventana emergente ni el amago de aparecer de la ventana de login de Google.
final GoogleHttpClient httpClient =
GoogleHttpClient(await googleUser.authHeaders);
// log("$googleUser");
final GoogleCalendar.CalendarApi calendarAPI = GoogleCalendar.CalendarApi(httpClient, );
// log("${calendarAPI.events.list(idCalendar)}");
final GoogleCalendar.Events calEvents = await calendarAPI.events.list(idCalendar,);
// log("${calEvents.items}");
// final List<GoogleCalendar.Event> appointments = <GoogleCalendar.Event>[];
final List<GoogleCalendar.Event> appointments = <GoogleCalendar.Event>[];

if (calEvents != null && calEvents.items != null) {
for (int i = 0; i < calEvents.items.length; i++) {
final GoogleCalendar.Event event = calEvents.items[i];
if (event.start == null) {
continue;
}
// Para cambiar el color de los eventos, hay que tocarlo en la clase GoogleDataSource, el método getColor, deveolver el color que queramos.
appointments.add(event);

}
}
// Cargamos los eventos generales de familias

final String idCalendarFAM = Utils.getIdCalendario("FAMILIAS");
final GoogleCalendar.Events calEventsFAM = await calendarAPI.events.list(idCalendarFAM);
if (calEventsFAM != null && calEventsFAM.items != null) {
for (int i = 0; i < calEventsFAM.items.length; i++) {
final GoogleCalendar.Event event = calEventsFAM.items[i];
if (event.start == null) {
continue;
}
// Para cambiar el color de los eventos, hay que tocarlo en la clase GoogleDataSource, el método getColor, deveolver el color que queramos.
appointments.add(event);
}
}
// log("${}");
return appointments;
}

And finally the GoogleDataSource class:


import 'package:flutter/material.dart';
import 'package:googleapis/calendar/v3.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';

class GoogleDataSource extends CalendarDataSource {
GoogleDataSource({List<Event> events}) {
this.appointments = events;
}
@override
DateTime getStartTime(int index) {
final Event event = appointments[index];
return event.start.date ?? event.start.dateTime.toLocal();
}
@override
bool isAllDay(int index) {
return appointments[index].start.date != null;
}
@override
DateTime getEndTime(int index) {
final Event event = appointments[index];
return event.endTimeUnspecified != null && event.endTimeUnspecified
? (event.start.date ?? event.start.dateTime.toLocal())
: (event.end.date != null
? event.end.date.add(Duration(days: -1))
: event.end.dateTime.toLocal());
}
@override
String getLocation(int index) {
return appointments[index].location;
}
@override
String getNotes(int index) {
final Event event = appointments[index];
return event.description == null || event.description.isEmpty
? event.summary
: event.description;
}
@override
String getSubject(int index) {
final Event event = appointments[index];
return event.summary == null || event.summary.isEmpty
? 'No Title'
: event.summary;
}
@override
Color getColor(int index){
return Color.fromRGBO(168, 173, 29, 1); // Le pone color de fondo a los eventos de Google.
}
}


I hope your reply and help.
Thanks.




IR Indumathi Ravichandran Syncfusion Team April 8, 2021 07:02 AM UTC

Hi nestor, 
 
Thank you for the update. 
 
Based on the shared code snippet, we have checked, and you have to map the recurrence rule for calendar appointments. Kindly specify the property override method to map the properties in the CalendarDataSource class.  
 
Code snippet: Mapping recuurenceRule using getRecurrenceRule method. 
 
class MeetingDataSource extends CalendarDataSource {  MeetingDataSource(List<Meeting> source){    appointments = source;}@override  String getRecurrenceRule(int index) {  return appointments[index].recurrenceRule;}}
 
You can refer the following documentation to know about the mapping.  
 
UG link:  
 
We hope that this helps you. Please let us know if you need further assistance. 
 
Regards, 
Indumathi R 



NE nestor April 8, 2021 09:51 AM UTC

Hello,
Thanks for replying but it doesn't work for me. The getter recurrenceRule doesn't exist for Event class. It shows the following error:


══════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building Container:
Class 'Event' has no instance getter 'recurrenceRule'.
Receiver: Instance of 'Event'
Tried calling: recurrenceRule

The relevant error-causing widget was
Container
lib/…/pages/calendario_escolar_page.dart:117
When the exception was thrown, this was the stack
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1      GoogleDataSource.getRecurrenceRule
package:efi_educa/…/providers/google_data_source.dart:55
#2      AppointmentHelper._createAppointment
package:syncfusion_flutter_calendar/…/appointment_engine/appointment_helper.dart:1321
#3      AppointmentHelper.generateCalendarAppointments
package:syncfusion_flutter_calendar/…/appointment_engine/appointment_helper.dart:1279
#4      _SfCalendarState._getAppointment
package:syncfusion_flutter_calendar/…/calendar/sfcalendar.dart:2314
...
════════════════════════════════════════════════════════════════════════════════
E/flutter ( 7483): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: Class 'Event' has no instance getter 'recurrenceRule'.
E/flutter ( 7483): Receiver: Instance of 'Event'
E/flutter ( 7483): Tried calling: recurrenceRule
E/flutter ( 7483): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter ( 7483): #1      GoogleDataSource.getRecurrenceRule
package:efi_educa/…/providers/google_data_source.dart:55
E/flutter ( 7483): #2      AppointmentHelper._createAppointment
package:syncfusion_flutter_calendar/…/appointment_engine/appointment_helper.dart:1321
E/flutter ( 7483): #3      AppointmentHelper.generateCalendarAppointments
package:syncfusion_flutter_calendar/…/appointment_engine/appointment_helper.dart:1279
E/flutter ( 7483): #4      _SfCalendarState._getAppointment
package:syncfusion_flutter_calendar/…/calendar/sfcalendar.dart:2314
E/flutter ( 7483): #5      _SfCalendarState.initState.<anonymous closure>
package:syncfusion_flutter_calendar/…/calendar/sfcalendar.dart:1909
E/flutter ( 7483): #6      _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter ( 7483): #7      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter ( 7483): #8      _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter ( 7483): #9      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter ( 7483): #10     Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter ( 7483): #11     Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter ( 7483): #12     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:254:13)
E/flutter ( 7483): #13     _SfCalendarState._loadDataBase (package:syncfusion_flutter_calendar/src/calendar/sfcalendar.dart)
package:syncfusion_flutter_calendar/…/calendar/sfcalendar.dart:1
E/flutter ( 7483): <asynchronous suspension>
E/flutter ( 7483):



NE nestor April 8, 2021 08:51 PM UTC

I've already fixed it. I've added this code:
@override
String getRecurrenceRule(int index) {
return appointments[index].recurrence == null ? "" : appointments[index].recurrence[0];
}

Because of the class Event of GoogleCalendar has the attribute recurrence that it's a List of String. You have to obtain the first String, 0 position, of this List.

Thanks!


SS SaiGanesh Sakthivel Syncfusion Team April 9, 2021 10:04 AM UTC

Hi Nestor,

Thank you for the update. 
 
  
We are glad to know that the reported issue has been resolved. Please let us know if you would require further assistance.  
  
Regards,
SaiGanesh Sakthivel 
 


Loader.
Up arrow icon