how to send list<dynamic> to flutter firestore - flutter

I have marge one list (test1) with other list (test2) and got list dynamic (marge1), I need to convert marge1 to Map<String, dynamic> to send it to firestore, so far I understand. But I became stuck. What will be the solution. My code are as follows:
margeFunction() {
List test1 = [
{
"id": 0,
"name": customerName,
"address": customerAddress,
"mobile": customerMobile,
"deliveryDate": selectedDate1,
},
];
test1.forEach((element) {
test2.forEach((e) {
if (e["id"] == element["id"]) {
marge1.add(getmarge1(
e["id"],
e["itemName"],
e["description"],
e["itemPrice"],
e["image"],
e["unit"],
e["selectedServiceInList"],
e["uniqueListItem"],
e["subTotalListItem"],
e["counter"],
element["name"],
element["address"],
element["mobile"],
element["deliveryDate"],
));
}
});
});
}
Map<String, dynamic> getmarge1(
int id,
String itemName,
String description,
String itemPrice,
String image,
String unit,
String selectedServiceInList,
String uniqueListItem,
int subTotalListItem,
int counter,
String name,
String address,
String mobile,
DateTime deliveryDate) {
final Map<String, dynamic> data = new Map<String, dynamic>();
data["id"] = id;
data["itemName"] = itemName.toString();
data["description"] = description.toString();
data["itemPrice"] = itemPrice.toString();
data["image"] = image.toString();
data["unit"] = unit.toString();
data["selectedServiceInList"] = selectedServiceInList.toString();
data["uniqueListItem"] = uniqueListItem.toString();
data["subTotalListItem"] = subTotalListItem.toString();
data["counter"] = counter.toString();
data["name"] = name.toString();
data["address"] = address.toString();
data["mobile"] = mobile.toString();
data["deliveryDate"] = deliveryDate.toString();
return data;
}
Now I need to send the merge1 list to firestore. I have tried but can't figured it out. Any help is appreciated.

marge1 is a List<Map<String, dynamic>> and you'll want to write each of the Map<String, dynamic> item and not convert the list itself to a Map<String, dynamic>.
You will need to use a batched write.
Batched Writes: a batched write is a set of write operations on one or
more documents.
Source
You can do that as shown below:
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
final WriteBatch writeBatch = firebaseFirestore.batch();
final CollectionReference collectionReference = firebaseFirestore.collection("collectionPath");
marge1.forEach((element) {
final DocumentReference documentReference = collectionReference.doc();
writeBatch.set(documentReference, element);
});
writeBatch.commit();
Checkout FlutterFire's BatchedWrite documentation

Related

How to append 2 Future lists into one in Dart?

I am new to Dart and relatively new to coding. I would appreciate some advice on this.
I have 2 api calls and I would like to merge their results into a single list. I am still trying to grasp the concepts of futures, so far I have understood that I can't just add the returned lists. Here's my code:
class ApiClient {
final Client _client;
ApiClient(this._client);
dynamic get(String path) async {
final response = await _client.get(
Uri.parse(
'${ApiConstants.BASE_URL}$path?api_key=${ApiConstants.API_KEY}'),
headers: {
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
return json.decode(response.body);
} else {
throw Exception(response.reasonPhrase);
}
}
}
class ResultsModel1{
List<Model1>? names;
ResultsModel1({this.names});
ResultsModel1.fromJson(Map<String, dynamic> json) {
if (json['results'] != null) {
names = <Model1>[];
json['results'].forEach((v) {
names!.add(Model1.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (names != null) {
data['results'] = names!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Model1{
final int id;
final int name;
const Model1({required this.id, required this.name});
factory Model1.fromJson(Map<String, dynamic> json){
return Model1(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson(){
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}
class ResultsModel2{
List<Model2>? titles;
ResultsModel2({this.titles});
ResultsModel2.fromJson(Map<String, dynamic> json) {
if (json['results'] != null) {
titles = <Model2>[];
json['results'].forEach((v) {
titles!.add(Model2.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (titles != null) {
data['results'] = titles!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Model2{
final int id;
final int name;
const Model2({required this.id, required this.title});
factory Model2.fromJson(Map<String, dynamic> json){
return Model2(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson(){
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}
abstract class API1{
Future<List<Model1>> getModel1();
}
class API1Imp extends API1{
final ApiClient _client;
API1Imp(this._client);
#override
Future<List<Model1>> getModel1() async{
final response = await _client.get('/baseurlextension');
final names = ResultsModel1.fromJson(response).names;
return names ?? [];
}
}
abstract class API2{
Future<List<Model2>> getModel2();
}
class API2Imp extends API2{
final ApiClient _client;
API2Imp(this._client);
#override
Future<List<Model2>> getModel2() async{
final response = await _client.get('/baseurlextension');
final titles = ResultsModel2.fromJson(response).titles;
return titles ?? [];
}
}
I want to finally get a new list let's say ObjectModel[id, title] where model2 is appended below model1
class ObjectImpl {
final API1Imp api1;
final API2Imp api2;
ObjectImpl(this.api1, this.api2);
#override
List<ObjectModel>>> getObject() async {
try {
final names = await API1Imp.getModel1();
final titles = await API2Imp.getModel2();
final objects = names + titles;
return objects;
}
}
}
but I guess it doesn't work like that. Can anyone please help out?
When using the + operator you can't merge two different list types.
When does it like:
final names = await API1Imp.getModel1();
final titles = await API2Imp.getModel2();
final objects = names + titles;
it will give you an error because it's a different type.
instead, you can do it like
final names = await API1Imp.getModel1();
final titles = await API2Imp.getModel2();
final objects = [...names ,...titles];
If you want names and titles to be in the same list just do this:
final objects = [...names, ...titles];
Otherwise, you need to process them individually to add titles to names like so:
final objects = [];
for (int i = 0; i < names.length; i++) {
objects.add('${names[i]} ${titles[i]}');
}
If you want something other than this, then provide some examples so that we understand exactly what you want.
but I guess it doesn't work like that
Instead, it does! It all comes down on your data structure and on what you want to achieve.
You can merge lists with the + operator, but the two list types must match (e.g. you can do [1,2,3] + [4,5,6] obtaining a List<int>, but you can't do add ['a','b','c'] like that).
You can obtain a List<Object> - if that's what you want - using the spread operator like this:
final futureListOne = Future.delayed(Duration(milliseconds: 750), () => [1,2,3]);
final futureListTwo = Future.delayed(Duration(milliseconds: 950), () => ['a','b','c']);
final listOne = await futureListOne;
final listTwo = await futureListTwo;
final mergedList = [...listOne, ...listTwo];
print(mergedList); // [1, 2, 3, a, b, c]
But is having a List<Object> desirable in your use case? That depends on what you need. Usually, having loose types around your code makes it less readable / reusable, but it really depends on the context.
Note. We can use Future.wait to await for both the futures in parallel and increase efficiency.
final lists = await Future.wait([futureListOne, futureListTwo]);
final listOne = lists[0];
final listTwo = lists[1];
Hope this helps.
Thanks everyone for the answers. After some struggle it worked like this
final names = await API1Imp.getModel1();
final titles = await API2Imp.getModel2();
final objects = [...names ,...titles];

Adding firestore subcollection fields into List

i am trying to add the fields of a subcollection into reviewsList. May i know how should I do that in the //To add to List// part?
The 'Reviews' collection contains 2 subcollections namely '1' and '2'. Both '1' and '2' each contain a map of 4 fields.
Below are the codes and screenshot of firestore:
List<dynamic> reviewsList = [];
Future _getReviews() async{
firestore.collection('shops').doc(widget.shop.id).collection('reviews').get()
.then((reviews){
reviews.docs.forEach((result) {
firestore.collection('shops').doc(widget.shop.id).collection('reviews').doc(result.id)
.get().then((reviewDocumentSnapshot) {
// To add to List //
});
});
});
}
the issue is related to misunderstanding of async. change your function as
Future _getReviews() async{
var reviews = await firestore.collection('shops').doc(widget.shop.id).collection('reviews').get();
reviews.docs.forEach((result) {
var reviewDocumentSnapshot= await firestore.collection('shops').doc(widget.shop.id).collection('reviews').doc(result.id);
//add this snapshot to list.
reviewsList[your_object.fromJson(reviewDocumentSnapshot)];
});
}
and your model class will be
class your_model {
String name;
String review;
int star;
String uid;
your_model({this.name, this.review, this.star, this.uid});
your_model.fromJson(Map<String, dynamic> json) {
name = json['name'];
review = json['review'];
star = json['star'];
uid = json['uid'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['review'] = this.review;
data['star'] = this.star;
data['uid'] = this.uid;
return data;
}
}

Flutter get value in object list

In my Home.dart
static _getList() async {
Network network = Network();
final List list = await network.getData();
print("jsonString");
print(list);
return list;
}
Result in console:
flutter: [{id: 1, calc: 000100, name: Test, date: 2018-03-29 12:45:26.9830000}]
I need to get the id's and names of this object and generate a list, to be read
You need to convert your json data to objects.
There are tools to help you generating object from json like json2Dart. The result is :
class MyObject {
int id;
String calc;
String name;
String date;
MyObject({this.id, this.calc, this.name, this.date});
MyObject.fromJson(Map<String, dynamic> json) {
id = json['id'];
calc = json['calc'];
name = json['name'];
date = json['date'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['calc'] = this.calc;
data['name'] = this.name;
data['date'] = this.date;
return data;
}
#override
String toString() {
return '$id';
}
}
You need to iterate over your list from getData() and call MyObject.fromJson() from each occurence :
var myObjetcs = [];
for (var item in list) {
myObjetcs.add(MyObject.fromJson(item));
}
//Now, do what you want with myObjects
Hope it will help you

Unable to access list item inside a class

I've been wrapping my head around this issue for the past 2 hours (keep in mind that I'm new to Flutter). I'm trying to check if I've set up everything properly for getting a movie list from OMDB. Everything seems okay except the fact that I don't know how to access something inside a list ie. originalTitle.
This is the model:
class MovieItem {
int page;
int totalResults;
int totalPages;
List<Results> results;
MovieItem({this.page, this.totalResults, this.totalPages, this.results});
MovieItem.fromJson(Map<String, dynamic> json) {
page = json['page'];
totalResults = json['total_results'];
totalPages = json['total_pages'];
if (json['results'] != null) {
results = new List<Results>();
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['page'] = this.page;
data['total_results'] = this.totalResults;
data['total_pages'] = this.totalPages;
if (this.results != null) {
data['results'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String posterPath;
int id;
String originalLanguage;
String originalTitle;
String title;
Results(
{this.posterPath,
this.id,
this.originalLanguage,
this.originalTitle,
this.title,});
Results.fromJson(Map<String, dynamic> json) {
posterPath = json['poster_path'];
id = json['id'];
originalLanguage = json['original_language'];
originalTitle = json['original_title'];
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['poster_path'] = this.posterPath;
data['id'] = this.id;
data['original_language'] = this.originalLanguage;
data['original_title'] = this.originalTitle;
data['title'] = this.title;
return data;
}
}
You are attempting to call a property on a List<Result> instead of Result. The property you are attempting to access exists on Result ... if there is a List of Result objects, what do you expect to return with movieItem.results.originalTitle? There could be any number of Result object with possibly different titles? If you just want to print them all out:
Future<MovieItem> movieItem() async {
var movieItem = await
client.movieItem();
movieItem.results.forEach((result) => print(result.originalTitle));
return movieItem;
}
The forEach will allow you to call the property and print it on every Result in the list
Your movieItem model class has list of result objects. So when you call the client.movieItem method the you get a MovieItem Object, and it you want to print the specific result item then just do this
print(movieItem.results[0].originalTitle)
and if you want to access all the objects from the result list then using for loop you can achieve it
for(int i=0;i<movieItem.results.length;i++)
{
print(movieItem.results[i].originalTitle);
}

How can we parse the result fetched from odoo using the odoo_api in flutter?

I used the odoo_api v1.0.2 package in order to fetch all the records from odoo.
final domain = [
["sale_ok", "!=", false]
];
var fields = ["name", "list_price"];
client
.searchRead("product.template", domain, fields)
.then((OdooResponse result) {
if (!result.hasError()) {
print("Succesful");
final data = result.getResult();
print("Total: ${data['length']}");
final records = ("${data["records"]}");
print(records);
} else {
print(result.getError());
}
});
I want to take individual record from the product list in odoo and display it as products in my flutter app.
Create a model like:
class ItemModel {
final int id;
final String type;
final int time;
final String text;
final bool dead;
ItemModel.fromJson(Map<String, dynamic> parsedJson)
: id = parsedJson['id'],
type = parsedJson['type'],
time = parsedJson['time'],
text = parsedJson['text'],
dead = parsedJson['dead'];
Map<String, dynamic> toMap() {
return <String, dynamic>{
"id": id,
"type": type,
"time": time,
"text": text,
"dead": dead,
};
}
}
And use like ->
final item = ItemModel.fromJson(parsedJson);