Related
How do I add a map to a type map field in Firebase using flutter?
Here is the code in the image
FirebaseFirestore.instance.collection('userNames').doc(docID).set(
{
'children': {
'childUserName': username.text,
'childPassword': password.text,
'childFirstName': firstName.text,
'childLastName': lastName.text,
'username': username.text,
'parentUID': currentUID,
'parentFirstName': parentFirstName,
'parentLastName': parentLastName,
'points': startingAmount.text,
'timestamp': DateTime.now().millisecondsSinceEpoch,
}
},
SetOptions(merge: true),
)
You can write a Children and Child data model, then write a toMap function using.
example:
class Children {
final Child child;
Children({
required this.child,
});
Map<String, dynamic> toMap() {
return {
'child': child.toMap(),
};
}
}
class Child {
final String hello;
Child({
required this.hello,
});
Map<String, dynamic> toMap() {
return {
'hello': hello,
};
}
}
I have a collections with field of rating and i want to iterate through the collection and add all the values. Finally i want to store it in a variable that can be accessed by all screen in flutter.
Any idea?
Here what i have tried so but failed
void calculateHomeTeamRating(){
int rating=0;
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('SelectedPlayersHome').snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData){
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final players = snapshot.data.docs;
List<int> homeRating = [];
for(var playerRating in players){
rating = rating + playerRating.get('Rating');
}
String textRating = rating.toString();
homeRating.add(rating);
return null;
},
);
}
}
Here is the collections and the fields that shows the player name and their rating:
You can create a model class to encode and decode incoming data from firestore and can use this model class to store data.
Create class to store player data.
class Player {
String playerName;
int rating;
String timestamp;
Player({this.playerName, this.rating, this.timestamp});
Player.fromJson(Map<String, dynamic> json) {
playerName = json['PlayerName'];
rating = json['Rating'];
timestamp = json['timestamp'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['PlayerName'] = this.playerName;
data['Rating'] = this.rating;
data['timestamp'] = this.timestamp;
return data;
}
}
Pass QuerySnapshot to calculateHomeTeamRating function and it will returns the List<Player> and use it accordingly. .
Future<List<Player>> calculateHomeTeamRating(
QuerySnapshot querySnapshot) async {
final List<Player> playerList = [];
final data = querySnapshot.docs;
if (data != null && data.isNotEmpty) {
for (var i = 0; i < data.length; i++) {
var model = Player.fromJson(querySnapshot.docs[i].data());
playerList.add(model);
}
return playerList;
} else {
return null;
}
}
}
use specific value(rating) from list of player
var List<int> ratings;
final players = snapshot.data.docs;
final list = calculateHomeTeamRating(players);
if(list!= null && list.isNotEmpty){
ratings = list.map((player)=> player.rating).toList();
}
if(ratings!= null && ratings.isNotEmpty){
print("Total given ratings: ${ratings.length}");
}
Am currently having an issue to retrieve data from Firebase on a specific field which is products of type ProductData ,is givng me cast error. I was wondering how to do this casting of a Firebase Map to my ProductData which is a class of Products.Below is my code.
ProductData
class ProductData{
String category;
String description;
String id;
String images;
bool isFeatured;
bool isPopular;
bool isPromotion;
String name;
double price;
int quantity;
ProductData({
#required this.category,
#required this.description,
#required this.id,
#required this.images,
#required this.isFeatured,
#required this.isPopular,
#required this.isPromotion,
#required this.name,
#required this.price,
#required this.quantity,
});
ProductData.fromDocument(DocumentSnapshot documentSnapshot){
id=documentSnapshot.data()['id'];
category= documentSnapshot.data()['category'];
description= documentSnapshot.data()['description'];
images= documentSnapshot.data()['images'];
isFeatured = documentSnapshot.data()['isFeatured'];
isPopular= documentSnapshot.data()['isPopular'];
isPromotion= documentSnapshot.data()['isPromotion'];
name = documentSnapshot.data()['name'];
price = documentSnapshot.data()['price']+.0;
quantity=documentSnapshot.data()['quantity'];
}
Map<String, dynamic> toMap() => {
"id":id,
"category": category,
"descripton": description,
"imgUrl": images,
"isFeatured":isFeatured,
"isPopular":isPopular,
"isPromotion":isPromotion,
"name":name,
"price":price,
"quantity":quantity,
};
Map<String, dynamic> toResumeMap(){
return {
"id":id,
"category": category,
"descripton": description,
"imgUrl": images,
"isFeatured":isFeatured,
"isPopular":isPopular,
"isPromotion":isPromotion,
"name":name,
"price":price,
"quantity":quantity,
};
}
factory ProductData.fromMap(Map<String, dynamic> json) => ProductData(
id: json["id"],
name: json["name"],
description: json["description"],
price: json["price"]+0.0,
);
}
The issue is on the cart Product I put a comment near by the line where is giving me the error.
CartProduct.dart
class CartProduct {
double totalPrice;
String deliveryLocation;
String userId;
int quantity;
double subtotal;
String id;
ProductData products;
DateTime date;
CartProduct(
{
//#required this.totalPrice,
#required this.products,
#required this.deliveryLocation,
#required this.quantity,
#required this.date,
#required this.userId,
#required this.id,
#required this.subtotal
}
);
CartProduct.fromDoucment(DocumentSnapshot document){
date=document.data()['date'];
deliveryLocation = document.data()['deliveryLocation'];
id = document.data()['id'];
products = document.data()['products']; // Here is where my issue is
quantity = document.data()['quantity'];
subtotal= document.data()['subtotal'];
userId=document.data()['userId'];
}
//Now we must also to Write the Data Into DB Based on our request.
//Create a String Dynamic Function to write into the DB
Map<String, dynamic> toMap(){
return {
//'totalPrice': totalPrice,
'products': products.toResumeMap(),
'quantity': quantity,
'deliveryLocation': deliveryLocation,
//'quantity': quantity,
'userId': userId,
'date': date,
'id': id,
'subtotal': subtotal
};
}
Map<String, dynamic> toResumeMap(){
return {
"id":id,
"category": products.category,
"description": products.description,
"imgUrl": products.images,
"isFeatured":products.isFeatured,
"isPopular":products.isPopular,
"isPromotion":products.isPromotion,
"name":products.name,
"price":products.price,
};
}
factory CartProduct.fromMap(Map<String, dynamic> json) => CartProduct(
// totalPrice: json["totalPrice"],
quantity: json["quantity"],
deliveryLocation: json["deliveryLocation"],
userId: json["userId"],
products: json['products'],
date: json["date"],
id: json["id"],
subtotal: json['subtotal']
);
}
Also find my Firebase Fields in the image.
Thanks in Advance
Helo, in your CartProduct class, products variable is a Class (ProductData) but in your methode CartProduct.fromDoucment your directly pass some data in products variable (you pass a dynamic data). You should initialize ProductData with data (document.data()['products']) before.
Change your variables to final. Rewrite the CartProduct.FromDocument to this:
factory CartProduct.fromDoucment(DocumentSnapshot document){
return CartProduct(
date: document.data()['date'],
deliveryLocation: document.data()['deliveryLocation'],
id: document.data()['id'],
products: document.data()['products'],
quantity: document.data()['quantity'],
subtotal: document.data()['subtotal'],
userId: document.data()['userId'],
);
}
This will return a new instance of CartProduct.
I am trying to save my Poll Object to Firebase Realtime DB, but I dont really know how to do that with my Poll Object because it has a List. I tried to find a tutorial how to map an object with map to firebase but didnt find any.
class Poll {
String id;
String name;
String description;
List<Question> questions;
Poll({this.name, this.description, this.questions});
Poll.fromSnapshot(DataSnapshot snapshot) {
id = snapshot.key;
name = snapshot.value['name'];
description = snapshot.value['description'];
questions = snapshot.value['questions'];
}
toJson() {
return {'name': name, 'description': description, 'questions': questions};
}
}
class Question {
String id;
String question;
String customAnswer;
Question.customAnswer({this.question, this.customAnswer});
Question.fromSnapshot(DataSnapshot snapshot) {
id = snapshot.key;
question = snapshot.value['question'];
customAnswer = snapshot.value['customAnswer'];
}
toJson() {
return {'question': question, 'customAnswer': customAnswer};
}
}
Here I try to write to DB:
RaisedButton(
onPressed: () async {
Poll poll1 =
Poll(name: 'poll1', description: 'desc1', questions: [
Question.customAnswer(
question: 'who am i', customAnswer: 'Ostap'),
Question.customAnswer(
question: 'who are you', customAnswer: 'test'),
]);
await databaseReference
.child('Polls')
.push()
.set(poll1.toJson());
},
child: Text('Write To DB'),
And here the error Im getting:
Exception has occurred.
ArgumentError (Invalid argument: Instance of 'Question')
Its caused on await databaseReference
Can somebody help me? Thanks in advance!
I have created a JSON from your code as
{
"id":"",
"name":"",
"description":"",
"questions": [
{
"id":"",
"question":"",
"customAnswer":""
}
]
}
Then to generate the dart classes Use this website. your object class will look like this.
class Welcome {
Welcome({
this.id,
this.name,
this.description,
this.questions,
});
String id;
String name;
String description;
List<Question> questions;
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
id: json["id"],
name: json["name"],
description: json["description"],
questions: List<Question>.from(json["questions"].map((x) => Question.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"description": description,
"questions": List<dynamic>.from(questions.map((x) => x.toJson())),
};
}
class Question {
Question({
this.id,
this.question,
this.customAnswer,
});
String id;
String question;
String customAnswer;
factory Question.fromJson(Map<String, dynamic> json) => Question(
id: json["id"],
question: json["question"],
customAnswer: json["customAnswer"],
);
Map<String, dynamic> toJson() => {
"id": id,
"question": question,
"customAnswer": customAnswer,
};
}
Now you will be able to call await ...set(poll1.toJson()); without any error
If you want to set your data in format that under each node every object has it id instead of 0, 1, 2 ... just like below map
deliveryCharges: 2
hasPromoCode: true
id: "-MhHzoacmGb5839WG9_C"
uid: "LcZXgcW2VAfz34qJbu6QCm3u2B32"
items:
-MhCGlHJLOExb3eXxR08
itemId: "-MhCElzl6B7FZMakA2Kr"
itemName: "Regular package"
itemPerPrice: 40
itemQuantity: 3
subtitle: "40 p.c"
variationId: "-MhCGlHJLOExb3eXxR08"
-MhCGlTiT2qy317c79_n
itemId: "-MhCElzl6B7FZMakA2Kr"
itemName: "Regular package"
itemPerPrice: 100
itemQuantity: 5
subtitle: "60 p.c"
variationId: "-MhCGlTiT2qy317c79_n"
Order class
class Order {
String id;
String uid;
int timestamp;
bool hasPromoCode;
String promoCode;
num promoDiscount;
num deliveryCharges;
num totalAmount;
List<Cart> items;
Order({
#required this.id,
#required this.uid,
#required this.timestamp,
#required this.deliveryCharges,
#required this.totalAmount,
#required this.items,
});
factory Order.fromMap(Map<dynamic, dynamic> map) {
return new Order(
id: map['id'] as String,
uid: map['uid'] as String,
timestamp: map['timestamp'] as int,
deliveryCharges: map['deliveryCharges'],
totalAmount: map['totalAmount'],
items: map['items'] == null ? [] :Cart.toOrderItemList(map['items']),
);
}
Map<dynamic, dynamic> toSetMap() {
return {
'id': this.id,
'uid': this.uid,
'timestamp': this.timestamp,
'deliveryCharges': this.deliveryCharges,
'totalAmount': this.totalAmount,
'items': Cart.toOrderMap(this.items),
} as Map<dynamic, dynamic>;
}
}
class Cart {
String itemId;
String variationId;
String itemName;
String subtitle;
num itemPerPrice;
int itemQuantity;
Cart({
this.itemId,
this.variationId,
this.itemName,
this.subtitle,
this.itemPerPrice = 0.0,
this.itemQuantity = 1,
});
factory Cart.fromMap(Map<dynamic, dynamic> map) {
return new Cart(
itemId: map['itemId'] as String,
variationId: map['variationId'] as String,
itemName: map['itemName'] as String,
subtitle: map['subtitle'] as String,
itemPerPrice: map['itemPerPrice'] ,
itemQuantity: map['itemQuantity'] as int,
);
}
Map<dynamic, dynamic> toMap() {
return {
'itemId': this.itemId,
'variationId': this.variationId,
'itemName': this.itemName,
'subtitle': this.subtitle,
'itemPerPrice': this.itemPerPrice,
'itemQuantity': this.itemQuantity,
} as Map<dynamic, dynamic>;
}
static Map<dynamic, dynamic> toOrderMap(List<Cart> cartItems) {
Map<dynamic, dynamic> orderMap = new Map<dynamic, dynamic>();
for (Cart cart in cartItems) {
orderMap[cart.variationId] = {
'itemId': cart.itemId,
'variationId': cart.variationId,
'itemName': cart.itemName,
'subtitle': cart.subtitle,
'itemPerPrice': cart.itemPerPrice,
'itemQuantity': cart.itemQuantity,
};
}
return orderMap;
}
static toOrderItemList(var map) {
Map values = map as Map;
List<Cart> cartItem = [];
values.forEach((key, data) {
final Cart connect = Cart.fromMap(data);
cartItem.add(connect);
});
return cartItem;
}
}
}
It is working fine, I set my Object list (cart items) and fetch as whole and convert Map of order to Order Object and then map of CartItem to List to cartItems.
I am facing an issue of snapshot.data to be null even if there is data in the DB.
below is the function I try to call when loading the screen. previously I was getting records but after adding some extra fields like the repeat column, it stopped working.
Future<List<LocalNotificationData>> getAllScheduleNotification() async {
final db = await database;
var res = await db.rawQuery('SELECT * FROM scheduleNotifications');
print("res : $res");
List<LocalNotificationData> list =
res.isNotEmpty ? res.map((c) => LocalNotificationData.fromMap(c)).toList() : [];
print("result : ${res.map((c) => LocalNotificationData.fromMap(c)).toList()}");
if(res != null){
return list;
}
}
to check whether their is the data or not in the db, I have print("res : $res"); for test and the output is as followed:
flutter:res:[
{
id:1,
notificationId:1,
title:Legs,
description:<ul><li>Loosen your necktie or belt.</li><li>Remove high-heels.</li></ul>,
days:'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
hour:3,
time:0,
repeat:1
},
{
id:2,
notificationId:1,
title:Legs,
description:<ul><li>Loosen your necktie or belt.</li><li>Remove high-heels.</li></ul>,
days:'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
hour:3,
time:0,
repeat:1
},
{
id:3,
notificationId:1,
title:Legs,
description:<ul><li>Loosen your necktie or belt.</li><li>Remove high-heels.</li></ul>,
days:'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
hour:3,
time:0,
repeat:1
},
{
id:4,
notificationId:1,
title:Legs,
description:<ul><li>Loosen your necktie or belt.</li><li>Remove high-heels.</li></ul>,
days:'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
hour:3,
time:0,
repeat:1
},
{
id:5,
notificationId:1,
title:Legs,
description:<ul><li>Loosen your necktie or belt.</li><li<…>
flutter:snapshot.data:null
the iussue is definatly here, as line below that does have a print result, but that is never printed.
List<LocalNotificationData> list =
res.isNotEmpty ? res.map((c) => LocalNotificationData.fromMap(c)).toList() : [];
code for LocalNotificationData is as below:
class LocalNotificationData {
static const String idField = 'id';
static const String notificationotificationIdField = 'notificationotificationId';
static const String titleField = 'title';
static const String descriptionField = 'description';
static const String daysField = 'days';
static const String hourField = 'hour';
static const String minuteField = 'minute';
static const String repeatField = 'repeat';
String id;
int notificationId;
String title;
String description;
String days;
int hour;
int minute;
bool repeat;
LocalNotificationData({this.id, this.notificationId, this.title, this.description, this.days, this.hour, this.minute, this.repeat});
factory LocalNotificationData.fromMap(Map<String, dynamic> json) => new LocalNotificationData(
id: json["id"].toString(),
notificationId: json["notificationId"],
title: json["title"],
description: json["description"],
days: json["days"],
hour: int.parse(json["hour"]),
minute: json["minute"] ?? 0,
repeat: json["repeat"] ?? 0,
);
Map<String, dynamic> toMap() => {
"id": id,
"notificationId": notificationId,
"title": title,
"description": description,
"days": days,
"hour": hour,
"minute": minute,
"repeat": repeat,
};
LocalNotificationData.fromDb(Map<String, dynamic> json, String id) {
this.id = id;
this.notificationId = json[notificationotificationIdField];
this.title = json[titleField];
this.description = json[descriptionField];
this.days = json[daysField];
this.hour = json[hourField];
this.minute = json[minuteField];
this.repeat = json[repeatField];
}
Map<String, dynamic> toJson() {
return {
idField: this.id,
notificationotificationIdField: this.notificationId,
titleField: this.title,
descriptionField: this.description,
daysField: this.days,
hourField: this.hour,
minuteField: this.minute,
repeatField: this.repeat,
};
}
#override
String toString() {
return 'id: $id, title: $title, notificationotificationId: $notificationId, days: $days, hour: $hour, minute: $minute, repeat: $repeat';
}
}
#princeoo7, i think your fromMap and toMap is incorrect. Should be,
factory LocalNotificationData.fromMap(Map<String, dynamic> json) => new LocalNotificationData(
id: json[idField],
notificationId: json[notificationotificationIdField],
.......
);
Map<String, dynamic> toMap() => {
idField: id,
notificationotificationIdField: notificationId,
..........
};
See if that helps.