Auto generate firebase tables from flutter model - firebase

I'm new to firebase and just downloaded a sample project. In the project there are many models such as the one below.
My question:
Is it possible to auto generate these keys IN firebase without manually adding each key by hand:
Flutter Model:
class CategoriesModel {
String id;
String name;
String order;
String photo;
String title;
CategoriesModel(
{this.id = '',
this.name = '',
this.order = '',
this.photo = '',
this.title = ''});
factory CategoriesModel.fromJson(Map<String, dynamic> parsedJson) {
return CategoriesModel(
id: parsedJson['id'] ?? '',
name: parsedJson['name'] ?? '',
order: parsedJson['order'] ?? '',
photo: parsedJson['photo'] ?? '',
title: parsedJson['title'] ?? '');
}
Map<String, dynamic> toJson() {
return {
'id': this.id,
'name': this.name,
'order': this.order,
'photo': this.photo,
'title': this.title
};
}
}

Firestore is a schemaless database. There is nothing built into the API or the console to auto-generate data for your.
But you can of course fairly easily generate data through the API. I typically start with a file with some data to test with, and then either simply import that upon connecting, or generate random models from the JSON data by adding a factory CategoriesModel.random factory method.

Related

Firebase, Flutter, Provider - Mapping, and Using Data via Provider

I'm new to flutter and firebase (and yes i know this question has been asked before).
But i've seen plenty of different ways to map firebase data into provider, and some reason cannot get a single to work.
I have this data structure. And all i wish, is to Map it into an class / object.
Firebase screenshot
This is my data model.dart:
#immutable
class Requests {
Requests({
this.name = '',
this.pairingId = 0,
});
final String name;
final double pairingId;
Requests.fromJson(Map<String, Object?> json)
: this(
name: json['name']! as String,
pairingId: json['pairingId'] as double,
);
Map<String, Object?> toJson() {
return {
'name': name,
'pairingId': pairingId,
};
}
}
#immutable
class UserDataTest with ChangeNotifier {
UserDataTest({
this.firstName = '',
this.lastName = '',
this.gender = '',
this.dateOfBirth,
this.userUID = '',
this.uidp = '',
this.pairingId = 0,
this.requests = const [],
});
UserDataTest.fromJson(Map<String, Object?> json)
: this(
firstName: json['firstName']! as String,
lastName: json['lastName']! as String,
gender: json['gender']! as dynamic,
dateOfBirth: json['dateOfBirth']! as DateTime?,
userUID: json['userUID']! as String,
uidp: json['uidp']! as String,
pairingId: json['pairingId']! as double,
requests: json['requests']! as List<Requests>,
);
late final String firstName;
final String lastName;
final dynamic gender;
final DateTime? dateOfBirth;
final String userUID;
final String uidp;
final double pairingId;
final List<Requests> requests;
Map<String, Object?> toJson() {
return {
'firstName': firstName,
'lastName': lastName,
'gender': gender,
'dateOfBirth': dateOfBirth,
'userUID': userUID,
'uidp': uidp,
'pairingId': pairingId,
'requests': requests,
};
}
}
But from here i dont have any solution that works just partly.
Again, my wish is to be able to just write, ex. user.firstName and display the first Name. How do i get to there?
I know im missing the call to firebase, but i haven't been successful in making one.
I dont know if have to do something inside the provider.
(Yes i have a multiprovider at the top of my tree
and a call to the provider where im using it or wanting to)
My suggestion: start over. Just start by creating a simple class manually with just a few of the fields from Firebase, and work your way out. For example use the UserDataTest and just make it a class:
class UserDataTest {
String? firstName;
String? lastName;
UserDataTest({ this.firstName, this.lastName });
factory UserDataTest.fromJson(Map<String, dynamic> json) {
return UserDataTest(
firstName: json['firstName'],
lastName: json['lastName'],
);
}
}
Try to keep these classes as plain as possible. Create other classes for your services and then make those extend ChangeNotifier, like to encapsulate your business logic and trigger notifications.
Then, from Firebase you will easily be able to do stuff like:
List<UserDataTest> userData = [];
FirebaseFirestore.instance.collection('userdata').get().then((QuerySnapshot snapshot) {
userData = snapshot.docs.map((doc) => UserDataTest.fromJson(doc.data())).toList();
});
My two cents.

How to create/update and retrieve data from nested objects in Cloud Firestore in flutter?

[![enter image description here][1]][1]I have a class that has one embedded array as well as a couple of objects. I can't figure out how to create/update and read to and from Cloud Firestore. I'm using flutter.
class ArtistModal {
final String artistName;
final String artistImage;
final String role;
ArtistModal({
required this.artistName,
required this.artistImage,
required this.role,
});
I am trying to embedded artistModal in test modal. I want to read it as a list in UI side. I can't quite figure it out how?
class TestModal {
final String id;
final String venueName;
final String eventName;
List<ArtistModal> artistModal = <ArtistModal>[];
TestModal({
required this.venueName,
required this.id,
required this.eventName,
required this.artistModal,
});
factory TestModal.fromJson(Map<String, dynamic> json) {
return TestModal(
venueName: json['venueName'] ?? '',
eventName: json['eventName'] ?? '',
artistModal: List.from(json['artistModal'] ?? ''),
id: json['id'] ?? '');
}
Map<String, dynamic> toMap() {
return {
'venueName': venueName,
'eventName': eventName,
'artistModal': artistModal,
'id': id,
};
}
}
Edited
Alright. And after this can I use this to create/update and read data from Cloud Firestore.
Stream<List<TestModal>> fetchListOfTest() {
return _testCollection.snapshots().map((event) => event.docs
.map((e) => TestModal.fromJson(e.data() as Map<String, dynamic>))
.toList());
}
Future<void> setTest(TestModal testModal) {
var options = SetOptions(merge: true);
return _testCollection.doc(testModal.id).set(testModal.toMap(), options);
}
Since I do not have enough reputation to write a comment, I couldn't ask you what you want to achieve here exactly. I'm assuming that you want to generate a list of ArtistModal and store it in artistModal attribute of class TestModal. If that's the case, you can change your factory method to something like this:
factory TestModal.fromJson(Map<String, dynamic> json) {
return TestModal(
venueName: json['venueName'] ?? '',
eventName: json['eventName'] ?? '',
artistModal: json['artistModal'] != null ?
List.generate(json['artistModal'].length, (index) => ArtistModal(
artistName: json['artistModal'][index]['name'],
artistImage: json['artistModal'][index]['image'],
role: json['artistModal'][index]['role'],
)) : [],
id: json['id'] ?? '');
}
I am assuming that json['artistModal'] contains a list of Map, where the map contains data related to artist modal.

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.
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.
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();

how to access a collection inside a firestore document and assign it as a list to my dart list inside my model?

how can i access a firestore collection inside a document and assign it to a list in my model, i tried accessing it like this snap.reference.collection('submittedUsers').get(); but i can't use async/await in constructors so i didn't knew what to do, this my model code:
final String fileUrl;
final String title;
final String description;
final List<String> submittedUsers;
LectureModel({
#required this.fileUrl,
#required this.title,
#required this.description,
this.submittedUsers,
}) : super(
fileUrl: fileUrl,
title: title,
description: description,
submittedUsers: submittedUsers,
);
Map<String, dynamic> toDocument() {
return {
'fileUrl': fileUrl,
'title': title,
'description': description,
};
}
factory LectureModel.fromSnapshot(DocumentSnapshot snap) {
// my submittedUsers collection is inside this `snap` document
// i want to get that collection and i assign it's memebers to my model submittedUsers list
final data = snap.data();
return LectureModel(
fileUrl: data['fileUrl'] as String,
title: data['title'] as String,
description: data['description'] as String,
);
}
}
Your data class looks just fine., but in your current structure, also add a list to your factory in the model, like this:
factory LectureModel.fromSnapshot(DocumentSnapshot snap, List<String> submittedUsersList) {
final data = snap.data();
return LectureModel(
fileUrl: data['fileUrl'] as String,
title: data['title'] as String,
description: data['description'] as String,
submittedUsers: submittedUsersList,
);
}
}
But you need to call your method LectureModel.fromSnapshot inside a function, or a future builder or stream builder for example. And also fetch the subcollection after getting the parent document
For example, you need a function like this, and put it in your widget where you need it.
Future<List<LectureModel>> getLectures() async {
QueryDocumentSnapshot snap = await FirebaseFirestore.instance.collection('NAME_OF_PARENT_COLLECTION').get();
List<LectureModel> lectureList=[];
//this will check that there actually is documents in firebase
if(snap.docs.isNotEmpty){
for(var singleSnapDocument in snap.docs){
//then you have to get the subcollection seperately for every
//document.
List<String> listOfsubmittedUsers =[];
listOfsubmittedUsers = await
FirebaseFirestore.instance.collection('NAME_OF_PARENT_COLLECTION')
.doc(singleSnapDocument.id).collection('submittedUsers')
.get().then((result)=> result.docs.map((e) => e.data().toString()).toList());
//this will add a LectureModel object into our list lectureList
lectureList.add(LectureModel.fromSnapshot(singleSnap, listOfsubmittedUsers));
}
}
print('Length of lectureList is: ' + lectureList.length.toString());
return lectureList;
}
Now, anywhere in your code, you can use onPressed or in initState and just call your function getLectures. i.e
onPressed: () async {List<LectureModel> listOfLecture = await getLectures();}
Your problem should be solved.

How can I convert the documents in a Firebase Collection into a Map (in Flutter)?

As the title says it. I really can't visualize differences between each of the snapshot methods stated by past questions. I keep getting null values when using snapshots and StreamBuilders.
just create model like this:
import 'package:cloud_firestore/cloud_firestore.dart';
class EmployeeData {
final DocumentReference reference;
String address;
String designation;
EmployeeData.data(
this.reference, [
this.address,
this.designation,
]);
factory EmployeeData.from(DocumentSnapshot document) => EmployeeData.data(
document.reference,
document.data['Address'],
document.data['Designation'],
);
void save() {
reference.setData(toMap());
}
Map<String, dynamic> toMap() {
return {
'address': address,
'designation': designation,
};
}
}
then pass document in it like this :
Map map = EmployeeData.from(snapshot).toMap()

Resources