LazyTurtle
LazyTurtle

Reputation: 105

Flutter Firestore Get a Map and generate objects out of it

Hello Guys I need help again,

I have stored two maps in one document in firestore. enter image description here

Now I want to get those two maps and generate an object (CalendarEvent) out of each training.

    class CalendarEvent {
      final String title;
      final String id;
      final String date;
    
      CalendarEvent({this.title, this.id, this.date});
    
    
      Map<String, dynamic> toMap() {
        Map<String, dynamic> map = {
          'title': title,
          'id': id,
          'date': date,
        };
      }
    
      factory CalendarEvent.fromJson(Map<dynamic, dynamic> json) {
    
        return CalendarEvent(
          title: 'null',
          id: 'null',
          date:'null'
        );
      }
    
    
    }

For each training I want to generate an object of CalendarEvents. I tried several things, but I think im stuck.

Stream<CalendarEvent> getTrainings() {
return _firestore
    .collection('users')
    .doc('${_authentication.getUID()}')
    .collection('user')
    .doc('trainings')
    .snapshots()
    .map((doc) => CalendarEvent.fromJson(doc.data()));
    
}
}

At the moment, the factory constructor of CalendarEvent is called just one time because of one document. Is there a possible way, to call the constructor 4 times (for each training in those two maps one time)?

Thanks in advance.

Upvotes: 0

Views: 510

Answers (1)

Peter Obiechina
Peter Obiechina

Reputation: 2835

I think what you are trying to achieve will be easily reached if you restructure your data.

Old data structure

users -> user_id -> user -> trainings -> data

New structure

users -> user_id -> trainings -> training_id -> data

I removed 'user' as a collection so that 'trainings' becomes a collection because this will allow you to fetch all trainings for all users or for a particular user easily.

e.g for your first training data (i.e: training1630319465118756)

users -> user_id -> trainings -> 1630319465118756 -> {name: 'Ok', date: 'August 30th, 2021'}

Then your getTrainings function becomes

Stream<CalendarEvent> getTrainings() {
  return _firestore
      .collection('users/${_authentication.getUID()}/trainings')
      .snapshots()
      .map((doc) => CalendarEvent.fromSnapshot(doc));
  // I used fromSnapshot above so that we can get the id of the document.
  // fromSnapshot function is shown below.
}

Change your CalendarEvent model to below

class CalendarEvent {
  final String title;
  final String id;
  final DateTime date;

  CalendarEvent({this.title, this.id, this.date});

  Map<String, dynamic> toMap(CalendarEvent instance) {
    Map<String, dynamic> map = {
      'title': instance.title,
      'id': instance.id,
      'date': fromDateTime(instance.date),
    };
    return map;
  }

  factory CalendarEvent.fromJson(Map<dynamic, dynamic> json) {
    return CalendarEvent(
      title: json['title'] as String,
      id: json['id'] as String,
      date: toDateTime(json['date'] as Timestamp),
    );
  }

  factory CalendarEvent.fromSnapshot(
      DocumentSnapshot<Map<String, dynamic>> snapshot) {
    Map<String, dynamic> json = snapshot.data();
    json['id'] = snapshot.id;
    // after adding id, we call your fromJson function
    return CalendarEvent.fromJson(json);
  }
}

Timestamp fromDateTime(DateTime val) =>
    val == null ? null : Timestamp.fromDate(val);
DateTime toDateTime(Timestamp val) => val?.toDate();

Upvotes: 1

Related Questions