How to make changes to a DocumentSnapshot/QueryDocumentSnapshot (FlutterFire) - firebase

I'm trying to make changes to a specific field in a DocumentSnapshot, but I cant figure out how to get the update method to work. I can't even find any documentation to help me figure it out.
whatever.data().update("Availability", (newValue) => whatever);
whatever is a documentsnapshot,'Availabilty' is the field I want to update,
and 'newValue' is the value I want to update the field in the fetched object itself and not in Firestore.

The DocumentSnapshot has a reference property which is the DocumentReference of this snapshot.
Then you can update the document like this:
whatever.reference.update({Availability: "NewValue"})
Edit: OP wanted to updated local variable only and not the data in Firestore which can be done by assigning the data to a variable and update it.
var myData = whatever.data()
myData['property'] = 'value'

Try this
whatever.doc().update({
"Availability": newValue,
});

FirebaseFirestore.instance
.collection('YOURCOLLECTION')
.doc(DOCUMENTID)
.update({'Availability': newValue}).then((value) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Success'),
),
);
}).onError((error, stackTrace) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error while updating document'),
),
);
});
YOURCOLLECTION is the name of your collection and DOCUMENTID is your document Id for which you want to update the data.

Related

Flutter: How can use FieldValue.arrayRemove?

How can I delete an array of array of objects from Firestore? I want to delete it inside a list.generate
Here is my database structure, I want to delete [{street A, number 25}]
List.generate(
...
IconButton(
icon: const Icon(CupertinoIcons.trash),
onPressed: () async {
try {
await FirebaseFirestore.instance
.collection('users')
.doc(data['uid'])
.update(
{
'adress':
FieldValue.arrayRemove(
??)
},
);
} catch (e) {
print(e);
}
},
),
)),
As I see in your screenshot, the adress field is not of type array, it's a Map:
So there is no way you can call FieldValue.arrayRemove. If you want to remove that field, then please use the following lines of code:
Firestore.instance.collection('users').document(data['uid']).set(
{'adress': FieldValue.delete()},
SetOptions(
merge: true,
),
)
Edit:
After you have updated the screenshot, now the adress field is indeed of type array:
If you want to delete a specific object from the array using FieldValue.delete(), you should use all the data in the object and not partial data. I have even written an article regarding updating an array of objects in Cloud Firestore:
How to update an array of objects in Firestore?
Edit2:
In code it should look like this:
Firestore.instance.collection('users').document(data['uid']).update({
'adress': FieldValue.arrayRemove(elementToDelete),
});
Please note that elementToDelete object should contain both fields populated. The number should hold the value of "25" and street should hold the value of "street A". It will not work if you use only one.
However, if you thought that Firestore provides a direct way to delete an array element by index, please note that is not possible. In such a case, you'll have to read the document, remove the element from the array, then write the document back to Firestore.

Flutter - How to add a field to all documents in firebase collection

I am using flutter firebase. And I want a query to add a key and value to all documents in firebase collection.
I try to use batch write but it add a new documents having field. But not merge to existing documents.
var db= Firestore.instance();
var batch = db.batch();
batch.setData(
db.collection("users").document(),
{"status": "Approved"}
);
When I try to give document Id like document('id') it add only to that document.
I try many and watches YouTube videos but not able find still now. Please help me !
Create a dummy button on one of the pages in your app. Pressing the button should add the field in all documents of the particular collection.
Here, I have used an IconButton to add an empty field called 'bio' in the 'users' collection.
You can delete the button later after you've added the field in your documents because this is your (developer's) problem, and your app user does not need the button.
IconButton(
onPressed: () {
FirebaseFirestore.instance
.collection('users')
.get()
.then(
(value) => value.docs.forEach(
(element) {
var docRef = FirebaseFirestore.instance
.collection('users')
.doc(element.id);
docRef.update({'bio': ''});
},
),
);
},
icon: Icon(Icons.done),
),
This is because you're using the setData() method, instead you should use the updateData() to update:
var db= Firestore.instance();
var batch = db.batch();
batch.updateData(
db.collection("users").document(),
{"status": "Approved"}
);

Exclude documents from firebase query using date

I have a model of posts which have a post time and expire time like so
class BuyerPost{
..some other properties...
final Timestamp postTime;
final Timestamp expireTime;
My intended outcome is that the expired posts will not be included in my query. If i could delete them from the database automatically the better but I would also work with just excluding them from my query.
I have tried to use the endAt and orderBy to achieve it but it failed
Stream <List<BuyerPost>> get sellerBuyerPosts {
try {
return buyerPostCollection.where('status',isEqualTo: 'available')
.orderBy('expireTime',descending: true)
.endAt([Timestamp.now()])
.snapshots()
.map(yieldSellerBuyerPosts);
}catch(e){
print(e.toString());
return null;
}
}
I also tried filtering on the client side but i got a type operator error because <,> is not available for time stamp
List<BuyerPost> yieldSellerBuyerPosts(QuerySnapshot snapshot) {
try {
return snapshot.documents.map((doc) {
return BuyerPost(
...some properties here...
postTime: doc.data['postTime']?? Timestamp(0,0),
expireTime: doc.data['expireTime']?? Timestamp(0,0),
);
}).where((post) =>
post.expireTime>Timestamp.now()
).toList();
}catch(e){
print(e.toString());
return null;
}
}
Am i using the wrong method or have i just made a slight error somewhere.
Don't use endAt in this query. That's for pagination, which you're not using here. If you want to constrain the range of values for a field, use another "where" filter to specify the range of values for that field:
return buyerPostCollection
.where('status', isEqualTo: 'available')
.where('expireTime', isLessThan: Timestamp.now())
.orderBy('expireTime', descending: true)
.snapshots()
The first method actually worked the only issue is that it does not work along with the stream. The only way you will see an update in post queries is with change of widget state, and you will find expired posts disappeared.

Update the Map field - Flutter

How to update data of isVerified (Boolean) field.
Personal Info is Map contains address and then isVerified.
To update isVerified, you have to do the following:
Firestore.instance.collection("collection Name").document("documentId").updateData({
"Personal Info.address.isVerified": true,
}).then((_) {
print("success!");
});
Since you did not provide your collection or document name I would just form one
So lets assume every time we click a button the value should be changed to true
CollectionReference humanCollection = Firestore.instance.collection("collection Name");
//This is the button
FlatButton(
onPressed: () => changeValue();
child : Container(
Text : 'Change Value'
)
),
//This is the function
changeValue(){
humanCollection
.document(currentHuman.id)//put the document name here
.updateData({
'Personal Info.address.isVerified' : true,
});
}
It is very easy use below line where ever you want to update data in firebase.
. is used to access key of sub-map.
await FirebaseFirestore.instance.collection('collection Name').doc('documentId').update({'Personal Info.address.isVerified' : true,});
version : cloud_firestore: 3.1.11

increment firebase field value in flutter?

I have a problem with that code below.
I want to create a blog app and I want to let people like posts and when someone clicks the like button it
should increase the field value in firebase and if he clicked again it decrements the value.
My Code : -
bool liked = false;
------------------
onPressed: () async {
await Firestore.instance
.collection('posts')
.document('${widget.uid}')
.updateData(
{
"likes": FieldValue.increment(
(liked ? (-1) : (1)),
),
},
);
setState(() {
liked = !liked;
});
},
Seems like your liked value go back to false even after the setState. Did you check liked before updating data. And could you show us exactly where do you declare your variable.
From your code it just seems like everytime you click the value of 'liked' is false. That makes your code to just increment the value by one. You have to check if the user has liked the post before and then change the state for the 'liked' bool.

Resources