Firebase does not retrieve fields in flutter - firebase

I'm trying to retrieve from my collection "Courses" 2 field.
Course code and Course name. My issue when retrieving is that I only managed to retrieve the first field.
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.separated(
itemCount: snapshot.data!.docs.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(height: 1),
// ignore: dead_code
itemBuilder: (context, index) {
DocumentSnapshot doc = snapshot.data!.docs[index];
return ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 30, vertical: 10),
selectedTileColor: Color(0xffE5E5E5),
title: Text.rich(
TextSpan(
text: doc["Course code"],
children: <TextSpan>[
TextSpan(text: ":"),
TextSpan(text: doc["Course name"]),
and it shows me this error:
Exception has occurred.
StateError (Bad state: field does not exist within the DocumentSnapshotPlatform)
this is my firebase
I only can retrieve course code I don't know why.

It seems like you have a problem with how Flutter and Firebase interacts with each other. I would like to suggest to check the following threadand especially the comment posted by jschnip which could solve your problem
This is probably related to recent changes in DocumentSnapshot, your
factory is looking for the data map, which used to be in doc, but nows
its in doc.data() - except DocumentID
So for your factory, one way to change it would be to adjust to:
Userr( id: doc.id, email: docdata['email'], username:
docdata['username'], url: docdata['url'], profileName:
docdata['profileName'], bio: docdata['bio'], subject1:
docdata['subject1'], subject2: docdata['subject2']
and when you call
it, you'll need to do something like:
doc.data();
newUserrr = Userr.fromDocument(doc, _docdata);

Related

Flutter - How to show ArrayList items pulled from Firebase Firestore with ListTile?

I have a build on Firebase Firestore like this:
In the structure here, there are 2 ArrayLists. I want to display what will be done from 2 ArrayLists as ListTile.
I tried a code like this:
Expanded(
child: StreamBuilder <QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("users").doc(FirebaseAuth.instance.currentUser.uid).collection("yapilacaklar").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return LinearProgressIndicator();
return Expanded(
child: _buildList(snapshot.data),
);
},
)
),
Widget _buildList(QuerySnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.docs.length,
itemBuilder: (context, index) {
final doc = snapshot.docs[index];
return ListTile(
title: Text(doc["yapilacaklar"].toString()),
);
},
);
}
These codes I tried do not give an error, but they do not show in any Widget. How can I do what I want? Thanks in advance for the help.
I believe the issue is the '.collection("yapilacaklar")'. It will try to find a collection with the id "yapilacaklar" and your user doc doesn't have any collections. Yapilacaklar, in this case, is a field in the document. Try getting the snapshots of the actual document and then creating a ListView from the array in the yapilacaklar field.
The flutterfire documentation is very helpful for reading firestore data: https://firebase.flutter.dev/docs/firestore/usage/#read-data

Error showing when document is deleted from firestore with streambuilder (flutter)

Hello everybody first of all I'm sorry for my English if its not clear, I'm working on a personal project. so, I'm using StreamBuilder on firestore document with the userID of the user from 'Users' Collections. So, I have retrieved the "imageUrl" field and display it in Image Network in my application, so, I have 'Delete Account' Button, this button will delete the account from firebase auth and also delete the document that the streambuilder listens to it.
So, the error happens because the streambuilder will build ImageNetwork and retrieve the URL from the document field.
Any ideas to handle the error?
this is the code for the streamBuilder that will return NetworkImage
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('Users')
.document(user.getID())
.snapshots(),
builder:
(context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print(snapshot.connectionState);
var userDocument = snapshot.data;
if (userDocument.data.length == 0) {
return const Center(
child: Text(
"Not Available",
style:
TextStyle(fontSize: 30.0, color: Colors.grey),
),
);
} else
return AvatarGlow(
glowColor: Colors.redAccent,
endRadius: 90,
child: Material(
elevation: 8.0,
shape: CircleBorder(),
child: CircleAvatar(
backgroundColor: Colors.grey[100],
child: ClipOval(
child: FadeInImage(
image: NetworkImage(
userDocument['imageUrl'] ??
'https://picsum.photos/250?image=9'),
placeholder: AssetImage('assets/noImage.png'),
),
),
radius: 70,
),
),
);
},
),
Debug error
The getter 'length' was called on null.
Receiver: null
Tried calling: length
The relevant error-causing widget was
StreamBuilder<DocumentSnapshot>
The solution was on if else blocks
StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('Users')
.document(user.getID())
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.data != null && snapshot.data.exists) {
var userDocument = snapshot.data;
// return something
}
}
For a non-existing document userDocument.data will return null, so userDocument.data.length throws the error you get.
My guess is you want to check if the document exists, which you'd do with:
if (userDocument.exists) {
Also see the reference documentation on DocumentSnapshot class, which is the type of object your userDocument is.
Ok. So, how these StreamBuilder(s) and FutureBuilder(s) are supposed be used are as follows:
Note: the following code should be inside your Builder function.
if(snapshot.hasData){
// Your normal functioning of the app will follow here.
// Now that you know that your snapshot contains data,
// then you access the data.
var userDocument = snapshot.data;
// Now, you can check if the userDocument exists or not.
}
else if(snapshot.hasError){
// return an error message or do something else.
}
// return any default Widget while the data is being loaded.
return CircularProgressIndicator();
Also, I would recommend that once the user requests to delete his/her account, you should navigate back to the home screen...

How to access specific data from firebase

I am new to firebase and I am wondering how would you access specific data. Ill give you an example, BTW I am using flutter.
Say I am creating data like this. I making a table of posts or I guess in firebase it'd be just a json array. In this json array I have 4 pieces of data state, city, post which as of right now just represents a simple message, and also timestamp.
So my question is how can I get a filtered version of my posts with a given city and state? Is there something special you can do in firebase? or would I have to do the filtering when I am building the list view?
I know FirebaseDatabase().reference().child('posts'); can access all of the posts.
var _firebaseRef = FirebaseDatabase().reference().child('posts');
_firebaseRef.push().set({
"state": state,
"city": city,
"post": post,
"timestamp": DateTime.now().millisecondsSinceEpoch
});
The code in the question means you are adding data, not retrieving. If you want to retrieve data according to a specific city then do the following query:
var dbRef = FirebaseDatabase().reference().child('posts');
dbRef.orderByChild("city").equalTo("city_name").once();
once() returns a Future so you can use the FutureBuilder to get the data from the above query.
Use Future Builder to fetch data to listview
create getPost() method first to return qn
Future getPosts() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection("your_collecttion_name").getDocuments();
return qn.documents;
}
after that use, future builder to fetch data
return Container(
child: FutureBuilder(
future: getPosts(),
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Text("Loading..."),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return Column(
children: <Widget>[
Text(
snapshot.data[index].data['your_data_field'] //name,age etc..
.toString(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500),
),]
),}
),
});

How to fetch data from firebase realtime database in flutter?

I'm building an app in Flutter in which I have data stored in the Firebase Realtime Database. I want to fetch those data in my app.
Now, Because of breaking changes made few months ago I'm unable to find new articles or video which might help but all I find are old ones so if anyone here can help me?
variable for the list
final dbRef = FirebaseDatabase.instance.reference().child("workshops");
now for showing the data I'm trying like this
return FutureBuilder(
future: dbRef.once(),
builder: (context,AsyncSnapshot<DataSnapshot> snapshot){
if(snapshot.hasData){
workshopList.clear();
Map<dynamic, dynamic> values = snapshot.data.value;
values.forEach((key,values){
workshopList.add(values);
});
}
return ListView.builder(
shrinkWrap: true,
itemCount: workshopList.length,
itemBuilder: (BuildContext context, index){
return Card(
child: Center(
child: Column(
children: [
Text("name "+ workshopList[index].workshopName)
],
),
),
);
},
);
}
);
For declaring list I was doing like this
List<Workshop> worskshopList = [];
but what worked for me was
List<Map<dynamic,dynamic>> workshopList = [];
And now for showing the data I am using
workshopList[index].workshopName
now problem with this is that I am not referencing database's workshopname but my model class' workshop name so I am getting nowhere.
now what worked for me was
workshopList[index]["workshopname"]
now from the old list I can't use like list[index][""] it will give an error like "[]" is not defined for the list.

Flutter: The method [] was called on null

I know this question is asked and answered many times but my problem is a bit different.
I am working with firebase realtime database in flutter. I upload a JSON file in the database for the existing data I have. It looks like this
Each child has 4 properties (Name, Location, Quality, Size)
The children have IDs of 0,1,2.....
When I retrieve this database in my app, it works and it is displayed perfectly.
When I create a new entry from my app, the child has a random ID and it looks like
this.
After that when I try to retrieve the values, the values are printed in the console but on the screen I get:-
The method [] was called on null error. Receiver: null. Tried Calling: []("Name")
.
The Error screen looks like this.
Error in console looks like this
My code for retrieving (I fetch and pass the variable to another screen):-
ref.once().then((DataSnapshot data) {
datatosend = data;
print(datatosend.value);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayList(
text: datatosend,
title: CategoryItemsitems[index].name),
));
});
My code for displaying listview:
itemCount: widget.text.value.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
leading: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
print("Edit Pressed!");
}),
title: Text(widget.text.value[index]["Name"]),
subtitle: Text("Quality: " +
widget.text.value[index]["Quality"] +
"\nSize: " +
widget.text.value[index]["Size"] +
"\nLocation: " +
widget.text.value[index]["Location"]),
trailing: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
print("Delete Pressed!");
}),
),
);
}),
My code for creating a new entry:
databaseReference.child(_category).push().set({
"Name": _name,
"Quality": _quality,
"Size": _size,
"Location": _location
}).then((_) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Successfully Added')));
});
Where am I going Wrong?
Hard to know without having access to the code, but this is usually what I do when I run into this type of issues:
run the code in debug mode and put a breaking right after this line:
itemBuilder: (BuildContext context, int index) {. This way you can introspect widget.text.value and see if it's really the array of objects you expected.
otherwise, use a good old print and start printing widget.text.value[index] in your itemBuilder (or even start by printing widget.text, then widget.text.value). You would be surprised how man bugs got figured out with a low-tech print function over the years ;-)
Good luck
After about 10 days, my problem is finally solved.
Some changes I made:
Instead of using, realtime database I am using Cloud Firestore.
Instead of importing the JSON file, I will enter the data manually. Fortunately, it is not very big and earlier also I was writing in the JSON file manually only.
Code to add the data to Firestore. All of this is inside the "onpressed" parameter of a button. All the inputs are taken by a simple form.
firestoreInstance.collection("cars").add({
"Name": _name,
"Quality": _quality,
"Size": _size,
"Location": _location,
}).then((value) {
print("Added Successfully")});
For fetching the data and access its different fields I am using a stream-builder:
StreamBuilder(
stream: Firestore.instance
.collection("cars")
.orderBy("Name") //To display the list by Name
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
else {
if(snapshot.data.documents.length>0)
{
return ListView.builder(
itemCount: snapshot.data.documents.length, //no. of entries fetched
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
snapshot.data.documents[index].data()["Name"]), //Accessing the Name property
subtitle: Text("Quality: " +snapshot.data.documents[index].data()["Quality"] + //Accessing the Quality property
"\nSize: " +snapshot.data.documents[index].data()["Size"] + //Accessing the Size property
"\nLocation: " +snapshot.data.documents[index].data()["Location"]) //Accessing the Location property
);
}
)}
}
}
}
)
I apologize if some of the closing parenthesis does not match. I pulled these important snippets from my very messy code.

Resources