please does anyone know how I can add the value coming from a populated map to an already initialized empty map?
type 1: This is just an example I am running on a flutter application to try it because of the hot reload feature. It's supposed to return the map in the map as a logged result. it returns an empty list since it is the value of the already initialized map. what I want is for it to return the added value from the map to the empty map and log.
class _ShowAppState extends State<ShowApp> {
final usermap = {
'docreference1': {
'college': 'Engineering',
'name': 'ola',
},
'docreference2': {
'college': 'Engineering',
'name': 'ola b',
},
'docreference3': {
'college': 'Engineering',
'name': 'ola a',
}
};
#override
Widget build(BuildContext context) {
final Map<String, String> stud = {};
// usermap.forEach((key, value) {
// final stud = value;
// stud;
// });
usermap.values.map((values) {
stud.addAll(values);
});
log('=====> $stud');
type 2: since my firebase request returns a map of map since I am querying a list of an object I need to pass the value of the map from Map<String,Map<String, dynamic>> to Map<String, dynamic>. and I can't return the value of .foreach or .map because their return type is null. so I thought to populate an already initialized empty list how can I archive this. without it returning null.
Future<Either<DtFailure, KtList<Student>>> viewAttendance(
String college, String department, String level) async {
try {
final snapshot = await _firebaseDatabase
.ref()
.child(
"studentsDetail/${_firebaseAuth.currentUser?.uid}/$college/$department/$level")
.orderByKey()
.get();
if (snapshot.exists) {
final KtList<Student> students = KtList.of();
// final students = DocRef.fromJson(data as Map<String, dynamic>);
final data = snapshot.value as Map<String, dynamic>;
data.forEach((key, value) {
final studentdata = value as Map<String, dynamic>;
final students = (studentdata)
.map((key, value) => MapEntry(
key, Student.fromJson(value as Map<String, dynamic>)))
.values
.toImmutableList();
students;
});
return right(students);
} else {
return right(const KtList.empty());
}
} on FirebaseException catch (e) {
if (e.message!.contains('PERMISSION_DENIED')) {
return left(const DtFailure.insufficientPermission());
} else {
return left(const DtFailure.unexpected());
}
}
}
In type 1, what is your expected output? If you want all the value from your key-value pair and store that in a variable then you can do something like this:
final usermap = {
'docreference1': {
'college': 'Engineering',
'name': 'ola',
},
'docreference2': {
'college': 'Engineering',
'name': 'ola b',
},
'docreference3': {
'college': 'Engineering',
'name': 'ola a',
}
};
final stud = (userMap.values).toList();
print(stud); // [{college: Engineering, name: ola}, {college: Engineering, name: ola b}, {college: Engineering, name: ola a}]
stud.forEach(print); /* {college: Engineering, name: ola}
{college: Engineering, name: ola b}
{college: Engineering, name: ola a} */
Now that you have a List<Map<String, String>> in variable stud, you can easily use the list's index to get the proper Map item.
If you were expecting for an output that looks something like this:
{
college: Engineering, name: ola,
college: Engineering, name: ola b,
college: Engineering, name: ola a
}
This is not possible as you can't have a Map with 2 or more keys being equal. Keys must be unique.
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'm working with data from Firebase RTDB. While I've successfully gotten the whole data from Firestore through this piece:
// GETTING ALL THE DATA FROM RTDB - MAP
void readSchool() async {
await realtime.once().then((DataSnapshot snapshot) {
setState(() {
schoolList = snapshot.value;
});
});
print('Data: $schoolList');
}
This is my RTDB data structure:
The Map I got from RTDB came out as nested Map (Map inside Map).
Data:
{
Kỹ thuật và Công nghệ:
{
color1: 0xfffaaca8, color2: 0xffb06ab3,
description: Nghiên cứu và sáng tạo các sản phẩm công nghệ cao,...,
oisp: {
imgcard: imgurl1,
category: KỸ THUẬT VÀ CÔNG NGHỆ,
title: Quốc tế Đại học Bách khoa TP.HCM,
location_s: Quận 10, Thành phố Hồ Chí Minh
}
},
Kinh tế và Quản lý:
{
color1: 0xffec6f66, color2: 0xfff3a183,
description: Tổ chức điều phối các hoạt động kinh tế, quản lý, tài chính,...,
ueh:
{
imgcard: imgurl2,
category: KINH TẾ VÀ QUẢN LÝ,
title: Đại học Kinh tế TP.HCM,
location_s: Quận 3, Thành phố Hồ Chí Minh}
}
}
Apparently, accessing a specific data using normal syntax such as
schoolList['Kỹ thuật và Công nghệ']['oisp'] doesn't trigger an analysis call of error but doesn't return a value neither.
Please help me access a specific data inside the data I retrieved from RTDB. Thank you!
I am trying to create some objects named HomeCard here:
// LIST OF ALL SCHOOL
Map schoolList;
// LIST OF FEATURED SCHOOL FROM FEATURED/RECOMMEND
List featuredSchool = [];
// LIST OF CATEGORIES FROM INFORMATION CATEGORIZE/LIST
List categories = [];
void homeCard() {
for (String category in categories) {
// ADD TO LIST
for (String school in featuredSchool) {
if (schoolList[category][school] as String != null) {
featuredCard.add(
// CARD TEMPLATE
HomeCard(
// FROM UNIVERSITY/INFORMATION/SCHOOL/[RECOMMENDED SCHOOL]/'TITLE'
name: schoolList[category][school]['title'] as String,
// FROM UNIVERSITY/INFORMATION/SCHOOL/[RECOMMENDED SCHOOL]/'CATEGORY'
category: schoolList[category][school]['category'] as String,
// FROM UNIVERSITY/INFORMATION/SCHOOL/[RECOMMENDED SCHOOL]/'IMGCARD'
networkImage:
NetworkImage(schoolList[category][school]['imgcard'] as String),
// CARD FUNCTION
function: () {},
),
);
String name = schoolList[category][school]['title'] as String;
print(name);
}
}
}
}
but it outputs an empty list
I'm struggling with a recursive loop and nested create/select statements. I'm receiving an object from a post request with the following structure:
11.6042
---11.6042_01
---11.6042_02
---11.6042_02
---14x10-100
------14x10-100_01
---14x10-100
------14x10-100_01
---14x10-100
------14x10-100_01
---M10-DIN929_14020
---M10-DIN929_14020
---11.6042_05
Wanted behaviour: travel through the structure recursive, add record to Part table, self join with parent part, join with PartLib table, if no match present create PartLib record and match created record. Process next part.
The problem: part 14x10-100 occurs three times in the structure. I want to create a record for part 14x10-100 in the part_lib table and refer to that record three times. What actually happens is that for each 14x10-100 part a corresponding record in the part_lib table is created in stead of one create and two matches. If I run it again it will match like excpected. I suspect I'm lost in the promise/async await parts of the code.
Below the relevant code. I've removed some attribute mappings for readability. My thoughts behind it: I'm not returning new promises like normal in a async function since Sequelize already returns a promise. When creating a part I'm awaiting (or at least I think so) the partLibController calls to ensure that all matching/creating/joining is done before proceeding to the next part in the structure.
Thanks a bunch!!
Recursive loop
function parseChild(child, modelId, parentId, userId, level) {
return new Promise((resolve, reject) => {
partController.create({
parent_id: parentId
, name: child.name
}, { id: userId }).then((part) => {
resolve({ child: child, level: level });
if (child.children) {
child.children.forEach(grandChild => {
parseChild(grandChild, modelId, part.part_id, userId, level + '---');
});
}
}).catch(error => { console.log(error); });
}).then((obj) => { console.log(`${obj.level} ${obj.child.name}`); });
}
PartController Create
async function create(partBody, currentUser) {
let { parent_id, name } = partBody;
const match = await partLibController.match(name);
let partLibId = null;
if (match.length == 0) {
const partLib = await partLibController.createFromPart(partBody, currentUser);
partLibId = partLib.part_lib_id;
} else {
partLibId = match[0].dataValues.part_lib_id
}
return ModelAssembly.create({
parent_id: parent_id
, name: name
, part_lib_id: partLibId
});
}
PartLibController Match
function match(name) {
return PartLib.findAll({
where: {
name: name
},
});
}
PartLibController CreateFromPart
function createFromPart(partBody, currentUser) {
let { name } = partBody;
return PartLib.create({
name,
});
}
Thanks to AKX I've solved the problem: hero
The problem was in the recursive call itself I suppose but here's the working code:
async function parseChild(child, modelId, parentId, userId, level) {
const body = {
parent_id: parentId
, name: child.name
};
const ma = await partController.create(body, { id: userId });
if (child.children) {
for (const grandChild of child.children) {
await parseChild(grandChild, modelId, ma.part_id, userId, level + '---');
}
}
return;
}
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.
The data I want to store looks like this
Class(
id: '0',
title: 'Yoga (Beginner)',
categories: ['1', '2'],
length: '30',
displayImage: './assets/images/yoga.png'),
)
but I have no idea how to store the categories list to Firestore, should I store it as a collection or normal field?
I have the below code to fetch the class information
class DataService {
final Firestore _db = Firestore.instance;
Stream<List<Class>> getClassesSnapshot() {
try {
var snaps = _db.collection('classes').snapshots();
snaps.handleError((e) {
print(e);
return Stream.empty();
});
return snaps.map(
(list) => list.documents.map((doc) => Class.fromSnap(doc)).toList());
} catch (e) {
return Stream.empty();
}
}
}
factory Class.fromSnap(DocumentSnapshot classSnap) {
return Class(
id: classSnap.data['id'],
title: classSnap.data['title'],
categories: classSnap.data['categories'],
length: classSnap.data['length'],
displayImage: classSnap.data['imageUrl'],
);
}
but it seems Firestore doesn't support "list" and it stopped at the categories field.
Thank you everyone.