Flutter how to add map to existing array on firebase - flutter

I am using this code to upload data to firebase:
List<Map<String, dynamic>> mapData = [
{
'name': 'name1',
'done': false,
'frequency': '1',
},
{
'name': 'name2',
'done': false,
'frequency': '5',
},
];
if (isExist == false && listNameController.text.isNotEmpty) {
await Firestore.instance
.collection(widget.user.uid)
.document(listNameController.text.toString().trim())
.setData({
'users': mapData,
});
But now I want to add more data.
I have tried this code but it overwrites all content. What can I do to just add the data to 'users'?
Firestore.instance
.collection(widget.user.uid)
.document(widget.currentList.keys.elementAt(widget.i))
.updateData({
'users': {
'name': 'name3',
'done': false,
'frequency': '7'
},

You can use arrayUnion to add array elements. Please use latest version of firestore package from pub.dev
Firestore.instance
.collection(widget.user.uid)
.document(widget.currentList.keys.elementAt(widget.i)).update({
"users": FieldValue.arrayUnion([new User]),
});

Related

How can I save two records with the id of the other in flutter?

How can I save two records with the id of the other in flutter?
I'm trying to save two records with id of the other, I can do that, but when I try to save more than 2 at same time some id come with blank. This is my code:
collectionReferenceRel.add({
'idRoom': id,
'room': rel,
'rel': room,
'id': '',
}).then((idRel) {
idRel1 = idRel.id;
},
);
collectionReferenceRel.add({
'idRoom': id,
'room': room,
'rel': rel,
'id': '',
}).then((value2) {
idNode2 = value2.id;
}).whenComplete(() async {
await collectionReferenceRel.doc(idRel1).update({
'id': idRel2,
});
await collectionReferenceRel.doc(idRel2).update({
'id': idRel1,
});
}).catchError((error) {
CustomFullScreenDialog.cancelDialog();
CustomSnackBar.showSnackBar(
context: Get.context,
title: 'Error',
message: 'Something went wrong',
backgroundColor: Colors.green);
[![enter image description here][1]][1] },
);
https://api.flutter-io.cn/flutter/dart-async/Future/wait.html
Future.wait([
collectionReferenceRel.add({
'idRoom': id,
'room': rel,
'rel': room,
'id': '',
}).then((idRel) {
idRel1 = idRel.id;
},
),
collectionReferenceRel.add({
'idRoom': id,
'room': room,
'rel': rel,
'id': '',
}).then((value2) {
idNode2 = value2.id;
})
]).whenComplete(() async {
await collectionReferenceRel.doc(idRel1).update({
'id': idRel2,
});
await collectionReferenceRel.doc(idRel2).update({
'id': idRel1,
});
}).catchError((error) {
CustomFullScreenDialog.cancelDialog();
CustomSnackBar.showSnackBar(
context: Get.context,
title: 'Error',
message: 'Something went wrong',
backgroundColor: Colors.green);
[![enter image description here][1]][1] },
);
Consider using the set() method provided the cloud firestore api.
Usage Example from the reference.
final city = <String, String>{
"name": "Los Angeles",
"state": "CA",
"country": "USA"
};
db.collection("cities")
.doc("LA")
.set(city)
.onError((e, _) => print("Error writing document: $e"));
For saving more than one document consider coupling it with the Future wait for a clean code.
/// Create a list to add all documents
final List docs = [];
/// create the documents with unique identifiers
/// beforehand using a package such as `Uuid`
final docA = {
'id': 'unique_identifier_a',
'idRoom': id,
'room': rel,
'rel': room,
}
docs.add(docA);
final docB = {
'id': 'unique_identifier_b',
'idRoom': id,
'room': rel,
'rel': room,
}
docs.add(docB);
/// Create futures from the documents
final futures = docs.map((e) => collectionRef.doc(e.id).set(e));
/// Save the documents in shot and wait for all
await Future.wait(futures);

Flutter - Get or access to matching map(s) from a List of Maps

Here I have a list of maps.
[
{
'name': 'name1',
'age': 30,
},
{
'name': 'name2',
'age': 20,
},
{
'name': 'name1',
'age': 15,
},
]
I need to access to 'name': 'name1' map from above list.
-- Access or extract maps --
i. e. List[0] and(or) List[2]
How do I do this kind of thing???
You can loop through the list and find items, .where will return list of found item. .firstWhere for single item return.
final data = [
{
'name': 'name1',
'age': 30,
},
{
'name': 'name2',
'age': 20,
},
{
'name': 'name1',
'age': 15,
},
];
final findValue = "name1";
final result = data.where((element) => element["name"] == findValue);
print(result); //({name: name1, age: 30}, {name: name1, age: 15})
result.forEach((element) {
print("${element["name"]} ${element["age"]}");
});
More about List

Dynamic list not maping from json Data

Dynamic list not maping from json Data
var jsondata = [
{
'value': '1',
'label': 'Red',
},
{
'value': '2',
'label': 'Green',
},
{
'value': '3',
'label': 'Yellow',
},
];
List<Map<String, dynamic>> _items = jsondata;
JSON Data not maping as variable with List<Map<String, dynamic>>.
You can use json_serializabl to parse JSON.
The document of official can teach you to do this.
Sample code from the document of official
Map<String, dynamic> user = jsonDecode(jsonString);
print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');
Ref: https://flutter.dev/docs/development/data-and-backend/json

Null value when retreived from a list map, but not null when printed as a string

Can't seem to find why the value is equal to null when in fact it isn't.
if I do a print(studioName); it will print the value retrieved from Firestore Database.
But when I try to retrieve it from the list, it will print as a null.
String studioName;
class Homne extends StatefulWidget {
#override
_HomneState createState() => _HomneState();
}
class _HomneState extends State<Homne> {
CollectionReference users = FirebaseFirestore.instance.collection('PopularPlacesList');
getPopularPlaces() async {
final snapShot = await FirebaseFirestore.instance
.collection('PopularPlacesList')
.doc('ksx1hVJn4Jf46ACFBbp7')
.get();
var data = snapShot.data();
studioName = data['name'];
}
var popularPlacesList = [
{
'name': '$studioName',
'image': 'assets/popular_places/miami.jpg',
'property': '783 properties'
},
{
'name': 'Singapore',
'image': 'assets/popular_places/singapore.jpg',
'property': '593 properties'
},
{
'name': 'New York',
'image': 'assets/popular_places/newyork.jpg',
'property': '1025 properties'
},
{
'name': 'Venice',
'image': 'assets/popular_places/venice.jpg',
'property': '290 properties'
},
{
'name': 'Vietnam',
'image': 'assets/popular_places/vietnam.jpg',
'property': '193 properties'
}
];
Where the code is presented in a list view builder:
Container(
width: width,
height: 150.0,
child: ListView.builder(
itemCount: popularPlacesList.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
var item = popularPlacesList[index];
popularPlacesList is initialized before getPopularPlaces has finished loading. One solution would be to set popularPlacesList via setState after you've finished loading your data from Firestore.
class _HomneState extends State<Homne> {
CollectionReference users = FirebaseFirestore.instance.collection('PopularPlacesList');
var popularPlacesList = [];
getPopularPlaces() async {
final snapShot = await FirebaseFirestore.instance
.collection('PopularPlacesList')
.doc('ksx1hVJn4Jf46ACFBbp7')
.get();
final data = snapShot.data();
final studioName = data['name'];
setState(() => popularPlacesList = [
{
'name': '$studioName',
'image': 'assets/popular_places/miami.jpg',
'property': '783 properties'
},
{
'name': 'Singapore',
'image': 'assets/popular_places/singapore.jpg',
'property': '593 properties'
},
{
'name': 'New York',
'image': 'assets/popular_places/newyork.jpg',
'property': '1025 properties'
},
{
'name': 'Venice',
'image': 'assets/popular_places/venice.jpg',
'property': '290 properties'
},
{
'name': 'Vietnam',
'image': 'assets/popular_places/vietnam.jpg',
'property': '193 properties'
}
]);
}
// Rest of your class
}

Flutter: how to return the value by using other value inside the List<Map>

I have a List<Map<String, String>> like below
[
{ 'name': 'John', 'id': 'aa' },
{ 'name': 'Jane', 'id': 'bb' },
{ 'name': 'Lisa', 'id': 'cc' },
]
And, the ID list **List** as ['bb', 'aa']. By using the ID list, I want to return a new list ['Jane', 'John'] as **List _selectedList**.
I have tried to do it with the .**indexWhere**, however, I am stuck on the List where it has more than one value.
How can I return the List only with the name-value when there is more than one value to look for?
void main() {
var a = [
{ 'name': 'John', 'id': 'aa' },
{ 'name': 'Jane', 'id': 'bb' },
{ 'name': 'Lisa', 'id': 'cc' },
];
var b = ['bb', 'aa'];
var c = a.where((m) => b.contains(m['id'])).map((m) => m['name']);
print(c);
}
Result
(John, Jane)
Use a set to filter out the IDs efficiently.
var ids = ["aa", "cc"];
var idSet = Set<String>.from(ids);
var json = [
{ 'name': 'John', 'id': 'aa' },
{ 'name': 'Jane', 'id': 'bb' },
{ 'name': 'Lisa', 'id': 'cc' },
];
var _selectedList = json.where((data) => idSet.contains(data["id"]))
.map((data) => data["name"]).toList();
print(_selectedList);
Here, .where filters out the data where the ID matches one in the input list "IDs". Sets make the process efficient. Then, the resultant objects are passed to .map where the "name" field is extracted. Finally, the whole thing is converted into a list thus returning the list of names.
Output of the above code:
[John, Lisa]