Search code examples
fluttersfcalendar

Flutter - SfCalendar - View not refreshing when changing the view


I am trying to create a view where the user can select the agenda view he wants (day, week, month...). In my appBar, I have created an action icon where the user can select the agenda view he wants. When I change the view, the set state does not refresh the agenda view. I do not find what I am missing.

If you could help, it will be appreciated. Thank you.

import 'package:syncfusion_flutter_calendar/calendar.dart';
import 'package:provider/provider.dart';


class CalendarWidget extends StatefulWidget {

CalendarView viewCalendar;
CalendarController _controller = CalendarController();

CalendarWidget(this.viewCalendar,this._controller, {Key? key}) : super(key: key);

  @override
  State<CalendarWidget> createState() => _CalendarWidgetState(viewCalendar,_controller);
}

class _CalendarWidgetState extends State<CalendarWidget> {
  CalendarView viewCalendar;
  CalendarController _controller;

  @override
  _CalendarWidgetState(this.viewCalendar,this._controller);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        myCalendar(context,viewCalendar,_controller),
        const SizedBox(height: 8.0),
      ],
    );
  }
}

Widget myCalendar (BuildContext context, view,_controler ) {

  final events = Provider.of<EventProvider>(context).events;
  final CalendarController _calendarControler = CalendarController();
  _calendarControler.view = view;

  return SfCalendar(
     view: CalendarView.month,

      // timeSlotViewSettings:
     // const TimeSlotViewSettings(allDayPanelColor: Colors.green),
      controller: _controler,
      _controler.view = view,
    //_controller.view = CalendarView.week,
      showNavigationArrow: true,
      showWeekNumber: true,
      showDatePickerButton: true,
      showCurrentTimeIndicator: true,
      initialSelectedDate: DateTime.now(),
      firstDayOfWeek: 1,
      dataSource: EventDataSource(events),
      onSelectionChanged: (details) {
        final provider = Provider.of<EventProvider>(context, listen: false);

        provider.setDate(details.date!);
      },
      onTap: (details) {
        final provider = Provider.of<EventProvider>(context, listen: false);

        if (provider.selectedDate == details.date) {

          showModalBottomSheet(
            context: context,
            builder: (context) => const TasksWidget(),
          );
        }
      },
      onLongPress: (details) {
        final provider = Provider.of<EventProvider>(context, listen: false);

        provider.setDate(details.date!);

        showModalBottomSheet(
          context: context,
          builder: (context) => const TasksWidget(),
        );
      },
    );
}

class AgendaOrganize extends StatefulWidget {
  const AgendaOrganize ({Key? key}) : super(key : key);
  @override
  _AgendaOrganizeState createState() => _AgendaOrganizeState();
}

class _AgendaOrganizeState extends State<AgendaOrganize> {
  CalendarView viewCalendar = CalendarView.month;
  final CalendarController _controller = CalendarController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        drawer:  const MyMenu(),
        appBar:  AppBar(
          title: const Center(
              child: Text('Agenda')),
          actions: <Widget>[
            PopupMenuButton
              (icon: const Icon(Icons.more_vert_outlined),
              itemBuilder: (BuildContext context) {
              return Menus.choice.map((String choice){
                return PopupMenuItem(
                 value: choice,
                 child: Text(choice));
              }).toList();
              },
            onSelected:
                choiceMade,
            ),

            IconButton(
              icon: const Icon(
                Icons.add_circle_outline,
                color: Colors.white,
              ),
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => const EventEditingPage()));
              },
            ),
          ],),
        body:  CalendarWidget(viewCalendar),

     //TODO //PROBLEME - SI J'AFFICHE PERSISTENTBOTTOMNAVBAR, affiche agenda FOR TODAY
     // bottomNavigationBar: PersistentBottomNavBar(),

    );
    throw UnimplementedError();
  }

  @override
  void setState(VoidCallback fn) {
    viewCalendar = CalendarView.month;
    super.setState(fn);
  }

  void choiceMade(String value) {
    print(value);
    setState(() {
      viewCalendar = CalendarView.month;
    });
  }
}

class Menus {
  static const List<String> choice = <String> [
    'Day', 'Week', 'Work Week', 'Month','Schedule', 'Timeline Day', 'Timeline Week', 'Timeline Work Week'
  ];
}

Solution

  • Just add a key to the SfCalendar and it's going to change on every setState. Do it like the following:

    Widget myCalendar(BuildContext context, CalendarView view) {
      final events = Provider.of<EventProvider>(context).events;
      final CalendarController _calendarControler = CalendarController();
      return SfCalendar(
        key: ValueKey(view),      // <- Here
        view: view,
        ...
    

    Also, the CalendarWidget is passing the state further down to the _CalendarWidgetState itself. The _CalendarWidgetState should use widget.viewCalendar instead.

    class CalendarWidget extends StatefulWidget {
      CalendarView viewCalendar;
    
      CalendarWidget(this.viewCalendar, {Key? key}) : super(key: key);
    
      @override
      State<CalendarWidget> createState() => _CalendarWidgetState();
    }
    
    class _CalendarWidgetState extends State<CalendarWidget> {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            myCalendar(context, widget.viewCalendar),
            const SizedBox(height: 8.0),
          ],
        );
      }
    }
    

    And here every choice possible:

    void choiceMade(String value) {
      setState(() {
        switch (value) {
          case 'Day':
            viewCalendar = CalendarView.day;
            break;
          case 'Week':
            viewCalendar = CalendarView.week;
            break;
          case 'Work Week':
            viewCalendar = CalendarView.workWeek;
            break;
          case 'Month':
            viewCalendar = CalendarView.month;
            break;
          case 'Schedule':
            viewCalendar = CalendarView.schedule;
            break;
          case 'Timeline Day':
            viewCalendar = CalendarView.timelineDay;
            break;
          case 'Timeline Week':
            viewCalendar = CalendarView.timelineWeek;
            break;
          case 'Timeline Work Week':
            viewCalendar = CalendarView.timelineWorkWeek;
            break;
        }
      });
    }