简体   繁体   English

如何在 Flutter 的 SfCalendar 数据源中显示来自 Firestore 的约会?

[英]How to display appointment from Firestore in SfCalendar's data source in Flutter?

I try to get appointments from Firestore to display them in datasource in SfCalendar .我尝试从Firestore获取约会以将它们显示在SfCalendar的数据源中。
I've tried 2 ways but in both case nothing is displayed.我尝试了 2 种方法,但在这两种情况下都没有显示任何内容。

Here is the code这是代码

Event事件

@JsonSerializable()
class Event {
  String uid;
  String title;
  DateTime from;
  DateTime to;
  String? comment;
  String backgroundColor;
  bool isAllDay;

  Event({required this.uid, required this.title, required this.from,
    required this.to, this.comment, required this.backgroundColor, this.isAllDay = false});

  factory Event.fromJson(Map<String, dynamic> json) => _$EventFromJson(json);

  Map<String, dynamic> toJson() => _$EventToJson(this);
}

EventDataSource事件数据源

class EventDataSource extends CalendarDataSource {

  EventDataSource(List<Event> appointments) {
    this.appointments = appointments;
  }

  Event getEvent(int index) => appointments![index] as Event;

  @override
  DateTime getStartTime(int index) => getEvent(index).from;

  @override
  DateTime getEndTime(int index) => getEvent(index).to;

  @override
  String getSubject(int index) => getEvent(index).title;

  @override
  Color getColor(int index) => Utils.getColorFromString(getEvent(index).backgroundColor);

  @override
  bool isAllDay(int index) => getEvent(index).isAllDay;
}

EventViewModel事件视图模型

class EventViewModel extends ChangeNotifier {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  final List<Event> _events = [];
  DateTime _selectedDate = DateTime.now();
  
  List<Event> get events => _events;

  List<Event> get eventsOfSelectedDate => _events;

  DateTime get selectedDate => _selectedDate;

  void setDate(DateTime date) => _selectedDate = date;

  Future createInstructorEvent(Event event) async {
    final eventDocument = _db.collection("instructorsEvent")
        .doc();

    final json = event.toJson();

    await eventDocument.set(json);
  }
}

CalendarWidget日历小部件

class CalendarWidget extends StatefulWidget {
  const CalendarWidget({Key? key}) : super(key: key);

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

class _CalendarWidgetState extends State<CalendarWidget> {
  @override
  Widget build(BuildContext context) {
    //final events = Provider.of<EventViewModel>(context).events;

    return Scaffold(
      body: SfCalendar(
        //dataSource: EventDataSource(events),
        view: CalendarView.month,
        onLongPress: (details) {
          final eventViewModel = Provider.of<EventViewModel>(context, listen: false);
          eventViewModel.setDate(details.date!);

          showModalBottomSheet(
              context: context,
              builder: (context) => const DailyWidget(),
          );
        },
      ),
    floatingActionButton: FloatingActionButton(
      child: const Icon(
        Icons.add,
        color: white,
      ),
      onPressed: () {
        _clickOnFAB(context);
      },
      ),
    );
  }

  void _clickOnFAB(BuildContext context) {
    Utils.goToEventPlanningScreen(context);
  }
}

Try #1尝试#1

I've tried what's explained in SfCalendar documentation but it doesn't work.我已经尝试过SfCalendar 文档中解释的内容,但它不起作用。

CalendarWidget日历小部件

class CalendarWidget extends StatefulWidget {
  const CalendarWidget({Key? key}) : super(key: key);

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

class _CalendarWidgetState extends State<CalendarWidget> {
  EventDataSource? events; //--------------------------------------- TODO 1
  final FirebaseFirestore _db = FirebaseFirestore.instance; //--------------------------------------- TODO 2

  @override
  void initState() {
    getInstructorEvent().then((results) {
      SchedulerBinding.instance.addPostFrameCallback((timeStamp) { //------------------------- TODO 3
        setState(() {});
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    //final events = Provider.of<EventViewModel>(context).events;

    return Scaffold(
      body: SfCalendar(
        dataSource: events, //--------------------------------------- TODO 5
        //dataSource: EventDataSource(events),
        view: CalendarView.month,
        onLongPress: (details) {
          final eventViewModel = Provider.of<EventViewModel>(context, listen: false);
          eventViewModel.setDate(details.date!);

          showModalBottomSheet(
              context: context,
              builder: (context) => const DailyWidget(),
          );
        },
      ),
    floatingActionButton: FloatingActionButton(
      child: const Icon(
        Icons.add,
        color: white,
      ),
      onPressed: () {
        _clickOnFAB(context);
      },
      ),
    );
  }

  void _clickOnFAB(BuildContext context) {
    Utils.goToEventPlanningScreen(context);
  }
  
  Future getInstructorEvent() async { //--------------------------------------- TODO 4
    var snapshot = await _db.collection(instructorsEvent)
        .get();

    List<Event> eventList = snapshot.docs.map(
            (e) => Event(
                uid: e.data()["uid"],
                title: e.data()["title"],
                from: DateFormat('dd/MM/yyyy HH:mm:ss').parse(e.data()['from']),
                to: DateFormat('dd/MM/yyyy HH:mm:ss').parse(e.data()['yo']),
                comment: e.data()["comment"],
                backgroundColor: e.data()["backgroundColor"],
                isAllDay: e.data()["isAllDay"],
            )
    ).toList();
    setState(() {
      events = EventDataSource(eventList);
      print("EventDataSource 1: $events");
    });
  }
}

Try #2尝试#2

EventViewModel事件视图模型

class EventViewModel extends ChangeNotifier {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  List<Event> _events = [];
  DateTime _selectedDate = DateTime.now();

  List<Event> get events => _events;

  List<Event> get eventsOfSelectedDate => _events;

  DateTime get selectedDate => _selectedDate;

  void setDate(DateTime date) => _selectedDate = date;

  Future createInstructorEvent(Event event) async {
    final eventDocument = _db.collection("instructorsEvent")
        .doc();

    final json = event.toJson();

    await eventDocument.set(json);
  }

  Future getInstructorEvent() async {
    var snapshot = await _db.collection(instructorsEvent)
        .get();

    List<Event> list = snapshot.docs
        .map((e) => Event(
      uid: e.data()["uid"],
      title: e.data()["title"],
      from: DateFormat("dd/MM/yyyy HH:mm:ss").parse(e.data()["from"]),
      to: DateFormat("dd/MM/yyyy HH:mm:ss").parse(e.data()["to"]),
      comment: e.data()["comment"],
      backgroundColor: e.data()["backgroundColor"],
      isAllDay: e.data()["isAllDay"],
    ))
        .toList();
  }
}

CalendarWidget日历小部件

class _CalendarWidgetState extends State<CalendarWidget> {
  Future<dynamic>? futureEvents; //--------------------------------------- TODO 1

  @override
  void initState() {
    futureEvents = _getInstructorEvent(); //--------------------------------------- TODO 2
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    //final events = Provider.of<EventViewModel>(context).events;

    return Scaffold(
      body: sfCalendarMonth(), //--------------------------------------- TODO 5
      floatingActionButton: FloatingActionButton(
        child: const Icon(
          Icons.add,
          color: white,
        ),
        onPressed: () {
          _clickOnFAB(context);
        },
        ),
      );
  }

  void _clickOnFAB(BuildContext context) {
    Utils.goToEventPlanningScreen(context);
  }

  _getInstructorEvent() async {
    final eventListTest = Provider.of<EventViewModel>(context, listen: false); //----------------- TODO 3
    eventListTest.getInstructorEvent();
  }

  Widget sfCalendarMonth() => FutureBuilder(
      future: futureEvents,
      builder: (context, AsyncSnapshot snapshot) {
        if(snapshot.hasData) {
          return SfCalendar(
            dataSource: snapshot.data, //--------------------------------------- TODO 4
            view: CalendarView.month,
            onLongPress: (details) {
              final eventViewModel = Provider.of<EventViewModel>(context, listen: false);
              eventViewModel.setDate(details.date!);

              showModalBottomSheet(
                context: context,
                builder: (context) => const DailyWidget(),
              );
            },
          );
        }
        return Container();
      },
  );
}

Try #3尝试#3

EventViewModel事件视图模型

class EventViewModel extends ChangeNotifier {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  final List<Event> _events = [];
  DateTime _selectedDate = DateTime.now();

  Future<dynamic> getInstructorEvent() async {
    var snapshot = await _db.collection(instructorsEvent)
        .get();

    List<Event> list = snapshot.docs
        .map((e) => Event(
      uid: e.data()["uid"],
      title: e.data()["title"],
      from: DateFormat("dd-MM-yyyyTHH:mm:ss").parse(e.data()["from"]),
      to: DateFormat("dd-MM-yyyyTHH:mm:ss").parse(e.data()["to"]),
      comment: e.data()["comment"],
      backgroundColor: e.data()["backgroundColor"],
      isAllDay: e.data()["isAllDay"],
    ))
        .toList();
    print("Appointments in VM: $list"); //------ return [Instance of 'Event']
  }
}

CalendarWidget日历小部件

class CalendarWidget extends StatefulWidget {
  const CalendarWidget({Key? key}) : super(key: key);

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

class _CalendarWidgetState extends State<CalendarWidget> {
  Future<dynamic>? _futureEvents; //---------------------------- TODO 1

  @override
  void initState() { //---------------------------- TODO 2
    _futureEvents = _getInstructorEvent();
    print("Appointments in initState 0: $_futureEvents"); //--- return Instance of 'Future<dynamic>' 'Future<dynamic>'
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final events = Provider.of<EventViewModel>(context).events;

    return Scaffold(
      body: sfCalendarMonth(),
    floatingActionButton: FloatingActionButton(
      child: const Icon(
        Icons.add,
        color: white,
      ),
      onPressed: () {
        _clickOnFAB(context);
      },
      ),
    );
  }

  //****************************************************************************
  // Click on FAB
  //****************************************************************************

  void _clickOnFAB(BuildContext context) {
    Utils.goToEventPlanningScreen(context);
  }

  Future<dynamic> _getInstructorEvent() async {
    final eventListTest = Provider.of<EventViewModel>(context, listen: false);
    dynamic eventList = await eventListTest.getInstructorEvent();
    return eventList; //---------------------------- TODO 3
  }

  Widget sfCalendarMonth() => FutureBuilder(
    future: _futureEvents, //---------------------------- TODO 4
    builder: (context, AsyncSnapshot<dynamic> snapshot) {

      final event = snapshot.data;
      print("Appointments in FutureBuilder 1: $event"); //-- return null
      if(snapshot.hasData) {
        return SfCalendar(
          dataSource: snapshot.data, 
          view: CalendarView.month,
          onLongPress: (details) {
            final eventViewModel = Provider.of<EventViewModel>(context, listen: false);
            eventViewModel.setDate(details.date!);

            showModalBottomSheet(
              context: context,
              builder: (context) => const DailyWidget(),
            );
          },
        );
      }
      return const Center(
        child: Text(
          "Nothing to show",
          style: TextStyle(
            fontSize: 24,
            fontWeight: FontWeight.bold,
          ),
        ),
      );
    },
  );
}

Thanks in advance提前致谢

Problem solved问题解决了

List<Event> events = [];
late Event event;

Widget小部件

Widget sfCalendarMonth() => StreamBuilder<QuerySnapshot>(
    stream: FirebaseFirestore.instance.collection(instructorsEvent).snapshots(),
    builder: (context, snapshot) {
        if(snapshot.hasData) {
          final eventDocument = snapshot.data!.docs;

          events.clear();

          for(var e in eventDocument){
            final uid = e.get("uid");
            final title = e.get("title");
            final from = e.get("from");
            final to = e.get("to");
            final comment = e.get("comment");
            final backgroundColor = e.get("backgroundColor");
            final isAllDay = e.get("isAllDay");

            event = Event(
                uid: uid,
                title: title,
                from: Utils.stringToDateTime(from),
                to: Utils.stringToDateTime(to),
                comment: comment,
                backgroundColor: backgroundColor,
                isAllDay: isAllDay,
            );
            events.add(event);
          }

          return SfCalendar(
            firstDayOfWeek: 1,
            dataSource: EventDataSource(events),
            view: CalendarView.month,
            onLongPress: (details) {
              final eventViewModel = Provider.of<EventViewModel>(context, listen: false);
              eventViewModel.setDate(details.date!);

              showModalBottomSheet(
                context: context,
                builder: (context) => const DailyWidget(),
              );
            },
          );
        }
        if(!snapshot.hasData) {
          return const Loader();
        }
        if(snapshot.hasError) {
          return Utils.showErrorMessage(snapshot.hasError.toString());
        }
        return Container();
      },
  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM