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

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.

Related

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.

Auto generate firebase tables from flutter model

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.

Data Not saving in real time database flutter

I have an application where i need to save data in real time database , i have setup code for authentication , storage and realtime database , auth and storage work fine but not the latter ,
i have tried different approach to make realtime db work but unfortunately nothing was successful , any help would be appreciated guys thank you.
This is how i init firebase
FirebaseApp app;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
app = await Firebase.initializeApp(
name: 'SecondaryApp',
options: const FirebaseOptions(
appId: '1:729669525962:android:b878xxxxxxxxxxxxx',
apiKey: 'AIzaSyD0w6UnBrWxxxxxxxxxxxxxxxxxxxxxx',
databaseURL: 'https://xxxxxxxxxxxx.appspot.com',
messagingSenderId: 'xxxxxxxxxxxxxxxx',
projectId: 'groceryfxxxxxxxxf6'
)
);
runApp(MaterialApp(
home: UserRegistrationScreen(),
debugShowCheckedModeBanner: false,
));
}
part 2
class _UserRegistrationScreenState extends State<UserRegistrationScreen> {
DatabaseReference itemRef;
final firebaseAuth = FirebaseAuth.instance;
final storage = FirebaseStorage.instance;
#override
void initState() {
super.initState();
itemRef = FirebaseDatabase.instance.reference().child('Users');
}
This is how i save data
BuyerModel model = new BuyerModel(
fullName,phone,country,state,city,address,
email,'online','Buyer', downloadUrl,DateTime.now().microsecondsSinceEpoch.toString(),
firebaseAuth.currentUser.uid);
itemRef.child(firebaseAuth.currentUser.uid).set(model);
This is the buyer model
class BuyerModel {
String fullName;
String phone;
String country;
String state;
String city;
String address;
String email;
String status;
String accountType;
String profileImage;
String timeStamp;
String userUid;
BuyerModel(this.fullName,this.phone,this.country,this.state,this.city,
this.address,this.email,this.status,this.accountType,this.profileImage,
this.timeStamp,this.userUid);
}
In Flutter I don't think the Firebase SDK knows how to write custom classes like BuyerModel. I usually end up with fromSnapshot and toMap methods to map back and forth.
An example of such a class:
class Question {
HUser owner;
String title;
List<String> answers;
int timeInSeconds;
String key;
Question(String this.title, List<String> this.answers, this.timeInSeconds, { this.owner }) {
}
Map<String, dynamic> toMap() {
return <String,dynamic>{
"owner": owner?.uid,
"title": title,
"answers": answers,
"timeInSeconds": timeInSeconds
};
}
Question.fromSnapshot(DataSnapshot snapshot): assert(snapshot != null),
title = snapshot.value["title"],
timeInSeconds = snapshot.value["timeInSeconds"],
owner = snapshot.value["owner"] != null ? HUser(snapshot.value["owner"]) : null,
key = snapshot.key;
}
I see now that I still need to read the answers back from the snapshot. That might explain a bug in my app. 😄

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

A simple Query in flutter/firebase database

I try to experience Firebase Live database with flutter.
I just would like to get a value in the datasnapshot of the firebase response.
My Firebase
My Code
static Future<User> getUser(String userKey) async {
Completer<User> completer = new Completer<User>();
String accountKey = await Preferences.getAccountKey();
FirebaseDatabase.instance
.reference()
.child("accounts")
.child(accountKey)
.child("users")
.childOrderBy("Group_id")
.equals("54")
.once()
.then((DataSnapshot snapshot) {
var user = new User.fromSnapShot(snapshot.key, snapshot.value);
completer.complete(user);
});
return completer.future;
}
}
class User {
final String key;
String firstName;
Todo.fromJson(this.key, Map data) {
firstname= data['Firstname'];
if (firstname== null) {
firstname= '';
}
}
}
I got Null value for firstname.
I guess I should navigate to the child of snapshot.value. But impossible to manage with foreach, or Map(), ...
Kind regards, Jerome
You are querying with a query and the documentation for Queries (here in JavaScript, but it is valid for all languages), says that "even when there is only a single match for the query, the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result."
I don't know exactly how you should loop, in Flutter/Dart, over the children of the snapshot but you should do something like the following (in JavaScript):
snapshot.forEach(function(childSnapshot) {
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
// ...
});
and assuming that your query returns only one record ("one single match"), use the child snapshot when you do
var user = new User.fromSnapShot(childSnapshot.key, childSnapshot.value);
This will give you Users in reusable dialog. There might be slight disservice to yourself if you don't use stream and stream-builders, the solution below is a one time fetch of the users' collection on FirebaseDB.
class User {
String firstName, groupID, lastName, pictureURL, userID;
User({this.firstName, this.groupID, this.lastName, this.pictureURL, this.userID});
factory User.fromJSON(Map<dynamic, dynamic> user) => User(firstName: user["Firstname"], groupID: user["Group_id"], lastName: user["Lastname"], pictureURL: user["Picturelink"], userID: user["User_id"]);
}
Future<List<User>> users = Firestore.instance.collection("users").snapshots().asyncMap((users) {
return users.documents.map((user) => User.fromJSON(user.data)).toList();
}).single;

Resources