.once() doesn't seem to work / recognized while working with Flutter & Firebase - firebase

I am trying to fetch some data from FireStore and store it in a local list to be displayed later in the form of cards. I have seen many tutorials where people have used .once() to fetch data.
Now, when I am trying to do the same then getting error like the word isn't recognized.
#override
void initState() {
super.initState();
CollectionReference dbRefItem = FirebaseFirestore.instance.collection("items");
***dbRefItem.once().then***
}
I cant seem to find any documentation if it has been deprecated or am I doing something wrong! Hovering cursor on the error says
"The method 'once' isn't defined for the type 'CollectionReference'.
Try correcting the name to the name of an existing method, or defining
a method named 'once'."

.get() did the same job as .once()
However, .once() syntax is not being accepted by Flutter's latest SDK while worked on the previous one. Have raised a ticket with Flutter Dev forum.

Related

Flutter Firestore not giving updated data when I add a field to a document from the console

I'm facing an odd bug in Flutter Firestore 2.5.3 where if I add a new field (customer_type) to a document in the Firebase Console, the app fails to retrieve the newly added field and throws an exception:
CastError (type 'Null' is not a subtype of type 'String' in type cast)
But it isn't null. I added the new field with the value from the Firebase Console. It's there in the document. Turns out Firebase is getting the old document data without the newly added field.
I'm using a StreamProvider from Riverpod. Here's the code:
static Stream<Customer?> _watchCustomer(final ProviderRefBase ref) async* {
final auth = await ref.watch(authProvider.last);
if (auth == null) {
yield null;
} else {
final customerRef = _db.collection('customers').toCustomerRef(auth.uid);
await for (var customer in customerRef.snapshots().map((doc) => doc.data())) yield customer;
}
}
What could be going wrong?
EDIT:
All the names, collection & field are correct and so is their type. If I re-install the app or fully clear app storage, the same exact code will work just fine. However, if I just clear the cache it doesn't work. It impedes my workflow when debugging and I'd like to know why it's happening. For additional reference, here is my "Customer" model:
Customer.fromMap(final String documentID, final Map<String, dynamic> map)
: id = documentID,
name = map['customer_name'] as String,
mobile = map['customer_mobile'] as String,
type = map['customer_type'] as String;
It's set to be non-nullable, because I'm establishing a strict schema. But that shouldn't be a concern, cause it isn't null in the database. I've added customer_type to all my documents in the collection. And none of them have the value set to null.
Which could only mean that the map that I get from Firestore, couldn't find the requisite key. Which means I'm still getting the old data (without the new field) from Firestore. What gives? It should give me the updated data when I clear the cache at least.
Because your code is working properly until you add the new field in Firestore console, it means that the problem is with your new field.
The problem is you either added a field in Firestore spelled differently (case sensitive or typo) from your model (class Customer) or the type is not appropriate (e.g. you try to read an int from a String, or you try to read an array from a map, etc.)
Let me know if this does not help?
What I know so far is that the stream returns an immediate local snapshot of the Document before fetching the updated version from the server. Which makes sense; except that if I clear the cache, then it should go to the server directly and not give me any error - which doesn't happen.
I think Firestore might be storing the local snapshot in more places than just the cache, but this is merely speculation on my end.
Currently, I've patched the issue by doing a simple null check in the constructor:
type = map['customer_type'] as String? ?? 'customer'
This fix is, however, inconclusive and I won't be marking this as the answer as I feel a proper explanation of what's happening is due.

Firestore document update is failing

i have documents in firestore which i am trying to update. These updates are successful for old users but failing for new users. I have listview where user can see all the added documents. They click on Edit and then they are navigated to a detailed document view where they can make changes and save.
Error which i am receiving
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception:
[cloud_firestore/not-found] Some requested document was not found.
I am passing document id with following from list view to single document edit view;
data: docId
In the edit page, i am loading the user id and doc id which is coming from previous page.
class Edit extends StatefulWidget {
final DataModel data;
Edit({required this.data});
String ui = FirebaseAuth.instance.currentUser!.uid;
#override
_EditState createState() => _EditState();
}
On save button i am updating firestore with following;
ElevatedButton.styleFrom(primary: Colors.redAccent),
onPressed: () async {
DocumentReference edit = FirebaseFirestore
.instance
.collection('edit')
.doc(ui)
.collection('edit')
.doc(widget.data.documentId);
edit.update({
});
The cloud_firestore/not-found error means the document was not found under the specified id. Please make sure the id really exists in your database.
If you are using the local emulator, make sure you are accessing the correct database.
If you are using persistent storage (offline firestore data) it might be that it still has old data or your device didn't connect to the internet and thus doesn't have the current data.
The error message is telling you that the document you build a reference to was not found for update.
There are a few ways to update data to Cloud Firestore:
update - change fields on a document that already exists.
Fails if the document does not exist.
set - overwrite the data in a document, creating the
document if it does not already exist. If you want to only partially
update a document, use SetOptions.merge(). If you want to be able to
create a document if it doesn't exist, or update it if it does
already exist, you should pass SetOptions.merge as the second
parameter, as explained by the API documentation.
So you just need to use the correct operation for your use case.
If you want to update a document without knowing if it exists or not,
you want to use a set() with the merge() option like this (this
example is for Java):
// Update one field, creating the document if it does not already exist.
Map<String, Object> data = new HashMap<>();
data.put("capital", true);
db.collection("cities").document("BJ") .set(data, SetOptions.merge());
Also one classical problem when using auth.currentUser is that it is
possible that the Auth object is not fully initialized and that
auth.currentUser.uid is therefore null. As explained in the doc you
should either use the onAuthStateChanged() observer or check that
auth.currentUser is not null.
Try :
ElevatedButton.styleFrom(primary: Colors.redAccent),
onPressed: ()
async {
DocumentReference edit = FirebaseFirestore .instance .collection('edit') .doc(FirebaseAuth.instance.currentUser.uid) .collection('edit') .doc(widget.data.documentId);
edit.update({ });

Flutter gives null error, but works after restart

I am new to Flutter, I am trying to fetch data from firestore collection. I am using FutureBuilder with Provider, but it shows null error on initial & runs perfectly after restarting the app.
Here is the code to fetch the data:
FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore.instance
.collection(collec.collectionProducts)
.get(),
builder: (context, snapshot) {
return Consumer<CartItemCounter>(
builder: (BuildContext context, CartItemCounter cart, _) {
if (cart.checkProductAddedToCart(model.productId)) {
return Row(....);
Error
code for futurebuilder
code for ui
(here i have changed the collection name)
How can i solve it. I have tried every solution available on online. Thank you
Where is the error coming from?
According to this, the issue is coming from your Consumer<CartItemCounter>.
What does the error mean?
This error, The method 'x' was called on null., means that the class where this x function is written, that class is null.
What is the reason for this error in my code?
Your Consumer<CartItemCounter> provides an instance of CartItemCounter by the name cart. Then, you call function checkProductAddedToCart.
The error message is telling you that cart is null which is being given to you by the Consumer widget. This means that Consumer probably also did not find that Provider. I expect that there should be an error log by Provider, telling you that CartItemCounter was not found.
Possible Solution
Try 'providing' CartItemCounter.
How do you do that? Go to the top of your app's widget tree to MaterialApp, wrap it inside a MultiProvider or ChangeNotifierProvider and then pass your new CartItemCounter as value.
Read Official Provider Docs for more info on how to expose a provider.
You need to upload your complete log, so that I can further help you.
Always check the result for the future builder, ie snapshot has data.
Place a switch condition or if-else bock depending on the status of the snapshot.
check the example from the official doc here

Retrieving snapshots from firestore sub-collection to dart/flutter object

New here. I've googled everything and can't figure this out.
The first two functions below work flawlessly the third always return null immediately without calling my ListFromSnapShot function, which just turns the map into a list. I am assuming
I'm not calling the Firestore correctly but I have no idea how to do this properly.
final CollectionReference customerCollection = Firestore.instance.collection('customers');
final CollectionReference jobCollection = Firestore.instance.collection('jobs');
// get user doc stream
Stream<UserData> get userData {
return customerCollection.document(uid).snapshots()
.map(_userDataFromSnapshot);
}
//Returns only snapshots with matching customer name to StreamProvider object
Stream<List<Job>> get jobQuery {
return jobCollection.where('customerName', isEqualTo: currentCustomer.companyName)
.snapshots()
.map(_jobListFromSnapshot);
}
//The following always returns Null
Stream<List<JobSectionModel>> get jobQuerySections {
return jobCollection.document('Family Dollar').collection('sections')
.snapshots()
.map(_jobSectionListFromSnapshot);
This is my database structure
Base Collection
Subcollection
Any help would be greatly appreciated.
The code above does work, the problem, after several frustrating days, ended up being random spaces in the firestore path. I'm posting this as an answer because after googling this there were many others with a similar problem and I don't want them to go through the same frustration. Firestore will not show this until you literally click on the path name and it will not crash your program, it just returns nothing.
Do yourself a favor and use the .trim() function when adding data and if you do it manually on firestore make sure there's no trailing spaces.
Also I rebuilt the code as follows which also works (without spaces of course)
Stream<QuerySnapshot> getjobQuerySections(BuildContext context) async*{
yield* jobCollection.document('T-MOBILE').collection('whyspaces').snapshots();
Hope this helps someone. Good Luck

how to obtain a particular document from a collection in firestore using Flutter

I am new to dart and so obviously to flutter... I did integrate firestore and did programming in android java.. and so I am finding it a little bit difficult to understand what means what in android java and flutter in regards to Firestore.
e.g. whats the alternative to addOnCompleteListener(android java) in flutter?
Regarding your question about how to get the document from collection you can refer the following code
DocumentReference documentReference =
Firestore.instance.collection("users").document("John");
documentReference.get().then((datasnapshot) {
if (datasnapshot.exists) {
print(datasnapshot.data['email'].toString(););
}
else{
print("No such user");
}
consider users collection has a document named as John with data as email: "j#gmail.com".
You can find the documentation very useful and almost all the functions are present for the flutter too. Just you should be able to do error and exception handling.
oncomplete() and listen() functions might be very helpful.
Hope it helped.

Resources