Trying to update a document with 7 fields (Flutter firestore) - firebase

Future _saveCourse(
String coursename,
String cid,
String coursecredit,
String coursetutor,
String coursetutoremail,
String coursetype,
String coursemajor) async {
await FirebaseFirestore.instance.collection('courses').doc(cid).update({
'coursename': coursename,
'coursecredit': coursecredit,
'coursetutor': coursetutor,
'coursetutoremail': coursetutoremail,
'coursetype': coursetype,
'coursemajor': coursemajor,
});
}
I am getting this error:
E/flutter (16143): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: [cloud_firestore/not-found] Some requested document was not found.

The message indicates that no document with the ID of your cid variable exists, and calling update is only valid on an existing document.

Related

Flutter: custom model returning null "List<dynamic> is not a subtype of List<String>" | "type 'Null' is not a subtype of type 'Product'"

I am calling a function that returns a future of custom model Products from Futurebuilder, and I am getting an error saying:
type 'Null' is not a subtype of type 'Product'
This is my Product model:
class Product {
#required
final String? id;
#required
final String? title;
#required
final String? discription;
#required
final double? price;
#required
final List<String>? info;
#required
final List<String>? imageUrl;
final String? category;
final offPerCent;
final String? seller;
Product({
this.id,
this.discription,
this.info,
this.imageUrl,
this.price,
this.seller,
this.title,
this.category,
this.offPerCent
});
}
And this is the function:
Future<Product> getbyId(String id) async {
var snapshot =
await firestore.collection('products').where('id', isEqualTo: id).get();
Map<String, dynamic> data = snapshot.docs[0].data();
return new Product(
id: data['id'],
title: data['title'],
price: data['price'],
seller: data['seller'],
category: data['category'],
discription: data['discription'],
imageUrl: data['imageUrl'],
info: data['info'],
offPerCent: data['offPerCent'],
);
}
I think there is some problem with the info and imageUrl field, both them are List<String> when I comment on both that line everything works fine.
Can someone help me out here?
Try
info: List<String>.from(data['info'])
Do the same for image.
Explanation:
The error that happened which displayed a message saying product is null, is actually caused by another error.
This error arises while creating your product object. And it happens in the fields mentioned above, where you specified a List<String> will come from Firebase. But Firebase SDK lists objects as List<dynamic>.
So probably there was another error in debug console saying
List<dynamic> is not a subtype of List<String> as in cast.
When you tell it to create a List from the elements inside the List, it works well, as long as those elements are actually strings. If you go to firebase, and change any of the items into anything besides string, you'll have another error saying int is not a subtype of type string for example.
Because creating a Product object from the map returned from firebase, goes through the steps in your method fromMap() in the model, it stops when it hits the error explained above, and therefore a product object never finishes creating it from a map.
Then, the widget waiting for the Product object to be returned, never receives what it was waiting for, you get the error in your original question.
type 'Null' is not a subtype of type 'Product'
You can avoid the third scenario, to account for anything coming from firebase, which is not a string, for example someone inputs an integer or double or null, by doing this:
info: List<String>.from(data['info'].map((element)=> element.toString()).toList());
This is an example:
List a = ['a', 1, '2', null]; //this is List<dynamic>
// List<String> b = List<String>.from(a); //This will give you an error when it encounters the number 1, it won't even continue.
List<String> b = List<String>.from(a.map((element) => element.toString()).toList());
print(b); // prints this => [a, 1, 2, null]
//because all the elements inside were converted to a string first.

How to store map data in array with Flutter Firestore

I try to make an app about health blog with Flutter. I want to store some data with arrays that contain map data. Although I can manually perform this on the Firestore, I'm getting some errors in coding.
Here is Firestore screenshot
Here is the code which I try to add map data to the array.
Future<bool> updateUserCases(String userId, Map newCase) async {
await _firestoreDB.collection("users").doc(userId).update({
"userCases" : FieldValue.arrayUnion([newCase])
});
return true;
}
I can add my map data to Firestore, but when I try to add it to the array, I get this error.
E/flutter (10661): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: [cloud_firestore/unknown] Invalid data. FieldValue.serverTimestamp() can only be used with set() and update()
And this is my "Case Model" which I want to add into the array
class CaseModel {
final String caseId;
final String caseTitle;
final String caseBody;
final Map caseOwner;
Timestamp caseDate;
bool caseSolve;
List<String> casePhotos;
String caseTag;
CaseModel(
{#required this.caseOwner,
this.caseId,
this.caseTitle,
this.caseBody,
this.caseDate,
this.caseTag});
Map<String, dynamic> toMap() {
return {
"case_id": caseId,
"case_title": caseTitle,
"case_body": caseBody,
"case_owner": caseOwner,
"case_date": caseDate ?? FieldValue.serverTimestamp(),
"case_solve": caseSolve,
"case_photos": casePhotos,
"case_tag": caseTag,
};
}
Could you help if there is a way I can fix this problem? Thank you.

After updating Flutter Firebase receive Bad State: field does not exist - QueryDocumentSnapshot

Prior to the update, document['field'] would result in null if it did not exist. Now it throws a Bad State error. The null response is needed because the field does not exist in some historical data and/or optional data in the Firebase collection. Confirmed this in the following report as well:
https://github.com/FirebaseExtended/flutterfire/issues/3826
Is there a way to capture the error and ignore it or set it to null or empty string?
static Pool dataFromDocument(QueryDocumentSnapshot document) {
return Pool()
..authUID = document.get('authUID')
..documentID = document.id
..propertyManagerID = document['propertyManagerID'] as String
}
static Stream<QuerySnapshot> getData(String authUID) {
CollectionReference poolRef = FirebaseFirestore.instance.collection(dataDB);
Query query = poolRef.where('authUID', isEqualTo: authUID.trim());
return query.snapshots();
}
With null safety, String is not nullable. However, String? is.
Change the line:
..propertyManagerID = document['propertyManagerID'] as String
To:
..propertyManagerID = document['propertyManagerID'] as String?
Your Pool will also have to have the property propertyManagerID as a String? in the class definition.

Future function was called on null (Flutter)

So I'm writing an quiz app and I need to get defined amount of questions from firestore. So i created two files data provider file and repository file, and that's how they look:
Data Provider
class TestProvider {
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<Map> getQuestionFromFirebase(String documentId) async {
Map mappedQuestion;
await _firestore
.collection('questions')
.doc(documentId)
.get()
.then((DocumentSnapshot snapshot) => mappedQuestion = snapshot.data());
return mappedQuestion;
}
}
Repository
class TestRepository {
final int amountOfQuestions;
TestRepository({
#required this.amountOfQuestions,
});
TestProvider _testProvider;
Future listOfQuestions() async {
List<int> range = numberInRange(amountOfQuestions);
List<Question> listOfQuestions;
for (int i = 1; i <= amountOfQuestions; i++) {
listOfQuestions.add(Question.fromMap(
await _testProvider.getQuestionFromFirebase(range[i].toString())));
}
return listOfQuestions;
}
}
The error i get:
E/flutter ( 5186): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'getQuestionFromFirebase' was called on null.
E/flutter ( 5186): Receiver: null
E/flutter ( 5186): Tried calling: getQuestionFromFirebase("3")
The funny thing about it is the fact that when i call fuction from provider i don't get error. Problem begins when I'm using it from repo class. Any idea how to fix it? I don't want to use FutureBuilder any time I want to use it in widget. I want to transform snapshot into my question model.
In your TestRepository code it's not clear where you are instantiating TestProvider _testProvider; member.
The error message is clear The method 'getQuestionFromFirebase' was called on null. So there is no instance of TestProvider class and _testProvider is a null pointer.
Grant TestProvider _testProvider = TestProvider(); in your code as said by #ikerfah and you will have no issues in your code.

Querying firebase real time database using firebase package unknown input parameter Flutter

I use firebase package for web version of my app and firebase_database for device version.
When querying a specific node using firebase_database the .once() method doesn't ask for any input parameter but firebase counterpart expects a String eventType input. I looked in the API docs but I couldn't find out what should be passed in..
What string should be passed in?
As always thank you very much for the help.
The firebase_database methods:
Future<DateTime> getFirebaseSyncDate(
String cityDb, String regionDb, String countryDb) {
// TODO: implement getFirebaseSyncDate
return ref
.child('Firebase Sync Date')
.orderByChild('Sync Date')
.limitToFirst(1)
.once()
.then((DataSnapshot snap) {
DateTime syncDate = snap.value['Sync Date'];
return syncDate;
});
}
and the firebase version:
Future<DateTime> getFirebaseSyncDate(
String cityDb, String regionDb, String countryDb) {
var ref = firebase.database().ref();
return ref
.child('Firebase Sync Date')
.orderByChild('Sync Date')
.limitToFirst(1)
.once('') // <=== String eventType ??
.then((snap) {
DateTime syncDate = snap.snapshot.val()['Sync Date'];
return syncDate;
});
}
once receive an eventType, one of the following strings: value, child_added, child_changed, child_removed, or child_moved.
In your case, I think it must be value
Check this link for more details

Resources