Iterate over firebase database nodes flutter - firebase

I want to iterate through the customers available and get the posts of every customer and show it inside a listview.
However, if i specify the database reference as final postsRef = FirebaseDatabase.instance.reference().child('Customers available').child(Uid).child('Posts').orderByChild('timestamp');, I get only the user's posts.
Below is my code for building the listview and another is my database reference. Thanks final postsRef = FirebaseDatabase.instance.reference().child('Customers available')
This is my Firebase Database Screenshot
future: postsRef.once(),
builder: (context, AsyncSnapshot<DataSnapshot> snapshot) {
if (snapshot.hasData) {
lists.clear();
Map<dynamic, dynamic> values = snapshot.data.value;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.grey[200]))
),
padding: EdgeInsets.all(SizeConfig.blockSizeHorizontal * 4),
child: Row(
children: <Widget>[
Container(
height: 50,
width: 50,
child: Container(
height: 50,
width: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(150),
image: DecorationImage(image: FirebaseImage('gs://tipy-98639.appspot.com/profile_pic'))
),
),
decoration: BoxDecoration(
color: Colors.grey,
image: DecorationImage(image: AssetImage('images/dp.png')),
borderRadius: BorderRadius.circular(150)
),
),
SizedBox(width: SizeConfig.blockSizeHorizontal * 3,),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('NAME', style: TextStyle(
fontFamily: 'myriadpro',
fontWeight: FontWeight.bold,
fontSize: SizeConfig.blockSizeVertical * 1.7
),),
SizedBox(height: SizeConfig.blockSizeVertical * 1,),
Text(lists[index]["text"],
maxLines: 20,
overflow: TextOverflow.clip,
style: TextStyle(
fontFamily: 'myriadpro',
fontSize: SizeConfig.blockSizeVertical * 1.7
),),
],
),
),
],
),
);
});
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.green),),
Text('Loading your posts... 🕑',
style: TextStyle(
fontFamily: 'myriadpro'
),
)
],
));
}),`

Related

How to retrive firebase subDocs - flutter

I want to retrieve a sub doc from Firebase, I need to collect the number of questions asked and answered by a particular user on their profile page, I am successfully retrieving the no of questions, cuz it's in the main doc,image 1, main doc, but I am not able to retrieve the answers, its a sub doc of questions image 2 sub doc, I tried playing with changing from AsyncSnaphot - DocumentSnapshot - dynamic, but no luck anywhere. Thanking you in advance.
```Widget followers(
BuildContext context, AsyncSnapshot<DocumentSnapshot> asyncSnapshot) {
return Container(
color: constantColors.green,
height: MediaQuery.of(context).size.height*0.09,
child: Row(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('questions')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Container();
} else {
return Provider.of<Authentication>(context, listen: false)
.getUserUid ==
asyncSnapshot.data.data()['user uid']
? Text(snapshot.data.docs.length.toString(), style: TextStyle(fontSize: 24),)
: Text('0');
}
}),
Text('asked'),
],
),
Column(
children: [
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('questions').doc().collection('answers')
.snapshots(),
builder: (context, snapshot){
if (snapshot.connectionState == ConnectionState.waiting) {
return Container();
} else {
return Provider.of<Authentication>(context, listen: false)
.getUserUid ==
asyncSnapshot.data.data()['user uid']
? Text(snapshot.data.docs.length.toString(), style: TextStyle(fontSize: 24),)
: Text('0');
}
}),
Text('answered')
],
)
],
),
);
} ```
Edit: Adding more code of my answer adding to the firebase feature
answerAdder(BuildContext context,
AsyncSnapshot<DocumentSnapshot> documentSnapshot, String QuesID) {
return showModalBottomSheet(
elevation: 0,
backgroundColor: Colors.transparent,
isScrollControlled: true,
context: context,
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height * 0.8,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 5),
decoration: BoxDecoration(
color: constantColors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(25), topLeft: Radius.circular(25)),
),
child: Column(
children: [
Divider(
indent: 110,
endIndent: 110,
thickness: 4,
color: Colors.grey,
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
MaterialButton(
onPressed: () {
Provider.of<PostFunctions>(context, listen: false)
.addAnswer(
context,
documentSnapshot.data.data()['question id'],
answerController.text,
titleController.text)
.whenComplete(() {
Navigator.pop(context);
});
Navigator.pop(context);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
color: constantColors.cyangrad,
child: Text(
'add answer',
style: TextStyle(fontWeight: FontWeight.w600),
),
)
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.2,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: TextField(
controller: answerController,
maxLines: 8,
cursorColor: constantColors.green,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15),
hintText: 'Please enter your answer',
isDense: true,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide.none),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide.none),
fillColor: Colors.grey[300],
filled: true),
),
),
),
Container(
height: MediaQuery.of(context).size.height * 0.2,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: TextField(
controller: titleController,
maxLines: 8,
cursorColor: constantColors.green,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15),
hintText: 'Please enter your title',
isDense: true,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide.none),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide.none),
fillColor: Colors.grey[300],
filled: true),
),
),
),
],
),
);
});}
Future method of uploading answer
Future addAnswer(BuildContext context, String postId,
String answer, String answerTitle) async {
return FirebaseFirestore.instance
.collection('questions')
.doc(postId)
.collection('answers')
.doc(answerTitle)
.set({
'answer': answer,
'username': Provider.of<FirebaseOps>(context, listen: false).initUsername,
'user uid':
Provider.of<Authentication>(context, listen: false).getUserUid,
'userimage':
Provider.of<FirebaseOps>(context, listen: false).initUserimage,
'useremail':
Provider.of<FirebaseOps>(context, listen: false).initUseremail,
'time': Timestamp.now(),
});
}
The issue is in .collection('questions').doc().collection('answers')
You need to pass the doc name in the doc() function. Consider it as a path!
By your example, it should be: .collection('questions').doc('hoo lala').collection('answers')

Adding a condition to retrieve certain data?

I want to add a conditional expression to the code so that the data that has the field 'category' entered as BS in firebase realtime database will be called and displayed. Here is a picture of the database table : https://imgur.com/a/PkdI71d
How do I add an expression to the following code so that only "English for Career Development" will be displayed and not "Excel Skills for Business" since "English for Career Development", or test 4 has a field category = 'bs' but test 5 doesn't so it will not show up.
Code:
class _BusinessPage1State extends State<BusinessPage1> {
List<AllCourses> coursesList = [];
#override
void initState(){
super.initState();
DatabaseReference referenceAllCourses = FirebaseDatabase.instance.reference().child('AllCourses');
referenceAllCourses.once().then(((DataSnapshot dataSnapshot){
coursesList.clear();
var keys = dataSnapshot.value.keys;
var values = dataSnapshot.value;
for(var key in keys){
AllCourses allCourses = new AllCourses(
values [key]["courseName"],
values [key]["teacher"],
values [key]["category"],
);
coursesList.add(allCourses);
}
setState(() {
//
});
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: ()
{Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context)=>homepage()));}),
title: Text("Creator's Club"),
backgroundColor: Color(0xff2657ce),
elevation: 0,),
body: Container(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Business', style: TextStyle(
color: Color(0xff2657ce),
fontSize: 27,
),),
Text('Choose which course you want to study.', style: TextStyle(
color: Colors.black.withOpacity(0.6),
fontSize: 20
),),
SizedBox(height: 10),
Expanded(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
coursesList.length == 0 ? Center(child: Text("Loading...", style: TextStyle(fontSize: 15),)): ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: coursesList.length,
itemBuilder: (_, index) {
return CardUI(coursesList[index].courseName, coursesList[index].teacher, coursesList[index].category);
}
)
]
),
),
),
]
)
)
);
}
}
Widget CardUI (String courseName, String teacher, String category){
return Card(
elevation: 1,
margin: EdgeInsets.all(5),
color: Color(0xffd3defa),
child: Container(
color: Colors.white,
margin: EdgeInsets.all(1),
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Color(0xffd3defa),
borderRadius: BorderRadius.all(Radius.circular(17)),
),
child: IconButton(
icon: Icon(
Icons.star_border_rounded ,
color: Color(0xff2657ce),
),
),
),
SizedBox(width: 15,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: InkWell(
onTap: (){},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(courseName, style: TextStyle(fontSize: 18)),
SizedBox(height: 5),
Text(teacher, style: TextStyle(fontSize: 15, color: Colors.grey)),
SizedBox(height: 5),
Text(category, style: TextStyle(fontSize: 15)),
],
),
)
)
]
)
]
)
],
)
),
);
}
Code for 'AllCourses' :
class AllCourses {
String courseName;
String teacher;
String category;
AllCourses(this.courseName, this.teacher, this.category);
}
Just add a condition to check if the category is 'bs' before adding the course to the coursesList:
for(var key in keys){
AllCourses allCourses = new AllCourses(
values [key]["courseName"],
values [key]["teacher"],
values [key]["category"],
);
if(allCourses.get('category') == 'bs')
coursesList.add(allCourses);
}

Closure call with mismatched arguments: function '[]' in flutter

** I am getting this error**
Closure call with mismatched arguments: function '[]'
Receiver: Closure: (dynamic) => dynamic from Function 'get':.
Tried calling: []("url")
Found: [](dynamic) => dynamic
my code where I am receiving the data from firestore is this..
import 'package:flutter/material.dart';
import 'package:riyazat_quiz/services/database.dart';
import 'package:riyazat_quiz/views/create_quiz.dart';
import 'package:riyazat_quiz/widgets/widgets.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Stream quizStream;
DatabaseService databaseService = DatabaseService(); // this is to call the getQuizData() async{
return await FirebaseFirestore.instance.collection("Quiz").snapshots();
}
Widget quizList(){
return Container(
child: StreamBuilder(
stream:quizStream ,
builder: (context,snapshort){
return snapshort.data == null ? CircularProgressIndicator(): ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount : snapshort.data.documents.length ,
itemBuilder : (context,index){ return QuizTile(url:snapshort.data.documents[index].get['url'],
title:snapshort.data.documents[index].get['title'] ,
desc: snapshort.data.documents[index].get['desc'],);}
);
}
),
);
}
#override
void initState() {
databaseService.getQuizData().then((val){
setState(() {
quizStream =val;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: appBar(context),
),
backgroundColor: Colors.transparent,
elevation: 0.0,
brightness: Brightness.light,
),
body:
Column(
children: [
quizList(),
FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => CreateQuiz()));
},
),
],
),
);
}
}
class QuizTile extends StatelessWidget {
final String url,title,desc;
QuizTile({#required this.url,#required this.title,#required this.desc});
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: [
Image.network(url),
Container(
child: Column(
children: [
Text(title),
Text(desc),
],
),
)
],
),
);
}
}
can someone tell me where I am going wrong
ps: this is a quiz app where I am getting the data from the firestore,
using streams.
data saved on the firestore has three fields, "url", "title" "desc".
I want to retrieve them in the below widget and want to display them in a stack, but this error got me stuck in-between.
You need to do the following:
itemCount : snapshort.data.docs.length ,
itemBuilder : (context,index){
return QuizTile(url:snapshort.data.docs[index].data()['url'],
title:snapshort.data.docs[index].data()['title'] ,
desc: snapshort.data.docs[index].data()['desc'],
);
}
);
Since you are reference a collection, then you need to use docs which will retrieve a list of documents inside that collection:
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/cloud_firestore/cloud_firestore/lib/src/query_snapshot.dart#L18
Then to access each field in the document, you need to call data()
The answer by #Peter Haddad is correct. Just to highlight the difference with an example from my own code:
The previous version of code which created the same error:
snapshot.data.docs[index].data["chatRoomID"]
Updated version of code which solved the error:
snapshot.data.docs[index].data()["chatRoomID"]
Updated Version:
snapshot.data[i]['Email'],
Future getRequests() async {
QuerySnapshot snapshot = await FirebaseFirestore.instance.collection("Buyer Requests").get();
return snapshot.docs;
}
body: FutureBuilder(
initialData: [],
future: getRequests(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
indexLength = snapshot.data.length;
if (snapshot.hasData)
return SizedBox(
child: PageView.builder(
itemCount: indexLength,
controller: PageController(viewportFraction: 1.0),
onPageChanged: (int index) => setState(() => _index = index),
itemBuilder: (_, i) {
return SingleChildScrollView(
child: Card(
margin: EdgeInsets.all(10),
child: Wrap(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage(
'assets/images/shafiqueimg.jpeg'),
),
title: Text(
snapshot.data[i]['Email'],
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: Colors.black.withOpacity(0.7),
),
),
subtitle: Text(
snapshot.data[i]['Time'],
style: TextStyle(
color: Colors.black.withOpacity(0.6)),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(5)),
color: Colors.grey[200],
),
padding: EdgeInsets.all(10),
child: Text(
snapshot.data[i]['Description'],
style: TextStyle(
color: Colors.black.withOpacity(0.6)),
),
),
SizedBox(
height: 8,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5)),
border: Border.all(
color: Colors.grey[300])),
child: ListTile(
leading: Icon(Icons.category_outlined),
title: Text(
'Category : ${snapshot.data[i]['Category']}',
style: TextStyle(
fontSize: 14,
color: Colors.grey,
),
),
),
),
SizedBox(height: 8),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5)),
border: Border.all(
color: Colors.grey[300])),
child: ListTile(
leading: Icon(Icons.location_pin),
title: Text(
snapshot.data[i]['Location'],
style: TextStyle(
fontSize: 14,
color: Colors.grey,
),
),
),
),
SizedBox(height: 8),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5)),
border: Border.all(
color: Colors.grey[300])),
child: ListTile(
leading: Icon(
Icons.attach_money,
color: kGreenColor,
),
title: Text(
'Rs.${snapshot.data[i]['Budget']}',
style: TextStyle(
fontSize: 14,
color: kGreenColor,
),
),
),
),
SizedBox(height: 8),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5)),
border: Border.all(
color: Colors.grey[300])),
child: ListTile(
leading: Icon(Icons.timer),
title: Text(
'Duration : ${snapshot.data[i]['Duration']}',
style: TextStyle(
fontSize: 14,
color: Colors.grey,
),
),
),
),
SizedBox(
height: 35,
),
RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10),
child: Text('Send Offer'),
textColor: Colors.white,
color: Colors.green,
onPressed: () {
// Respond to button press
},
),
SizedBox(
height: 15,
),
Center(
child: Text(
"${i + 1}/$indexLength",
style: TextStyle(fontSize: 13),
),
),
],
),
),
],
),
),
);
},
),
);
else
return Center(
child: Text("Null"),
);
},
),
Given that you are referencing a collection, you must use docs to acquire a list of the documents included in that collection:
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/cloud firestore/cloud firestore/lib/src/query snapshot.dart#L18
then you must call data() in order to access each field in the document.

Show Spinner using ModalProgressHUD in Flutter whilst ListView.builder reads information from Firebase

I have a screen where I try to read all my documents as a list using a Listview.builder in Flutter. I want to use ModalProgressHUD to show circular spinner whilst data is read from Firebase. When it's done building, I want to stop showing circular spinner by setting showSpinner to false.
I can hack this for a form screen but can't seem to for this view all screen, perhaps it's because it's a Listview.builder.
Thanks in advance.
Code below:
//class wide declaration
bool showSpinner = true;
Widget build(BuildContext context) {
ExpenseNotifier expenseNotifier = Provider.of<ExpenseNotifier>(context);
Future<void> _resfreshList() async {
expenseNotifier.getExpenses(expenseNotifier);
}
return Scaffold(
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: RefreshIndicator(
onRefresh: _resfreshList,
child: Consumer<ExpenseNotifier>(
builder: (context, expense, child) {
return expense == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
PaddingClass(bodyImage: 'images/empty.png'),
SizedBox(
height: 20.0,
),
Text(
'You don\'t have any expenses',
style: kLabelTextStyle,
),
],
)
: ListView.separated(
itemBuilder: (context, int index) {
var myExpense = expense.expenseList[index];
return Card(
elevation: 8.0,
color: Colors.white70,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
RegularExpenseTextPadding(
regText:
'${_formattedDate(myExpense.updatedAt)}',
),
Container(
margin: EdgeInsets.all(20.0),
padding: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(5.0)),
border: Border.all(
color: kThemeStyleBorderHighlightColour),
),
child: Row(
children: <Widget>[
Expanded(
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
'${myExpense.amount}',
style: kRegularTextStyle,
),
SizedBox(
height: 20.0,
),
Text(
myExpense.description,
style: kRegularTextStyle,
),
],
),
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
expenseNotifier.currentExpense =
expenseNotifier
.expenseList[index];
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) {
return ExpenseDetailsScreen();
}));
},
child: Icon(
FontAwesomeIcons.caretDown,
color: kThemeIconColour,
),
),
),
],
),
),
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 20.0,
);
},
itemCount: expenseNotifier.expenseList.length,
);
},
),
),
),
);
}

Firebase Streambuilder

I have a map in Firebase Database like this,
'abc#gmail.com' : { food order }
I want to create a stream of this data to update widgets when a new order is placed.
I tried using the below code but it is giving error.
DocumentSnapshot has no instance getter 'length'
StreamBuilder(
stream: Firestore.instance.collection('admin').document('current-orders').snapshots(),
builder: (context, snapshot) {
return snapshot.hasData?Column(
children: <Widget>[
Expanded(
child: Container(
child: Padding(
padding: EdgeInsets.all(10),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, uid) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
snapshot.data.keys.toList()[uid],
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
color: Colors.blue[200],
child: Text(
'Order Ready',
style: TextStyle(color: Colors.black54),
),
onPressed: () {},
),
],
),
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: snapshot.data.values.keys.toList().length,
itemBuilder: (context, orderID) {
return Text(
'${snapshot.data.values.keys[orderID].toString()} : ${snapshot.data.values.values[orderID].toString()}',
//'${_currentOrders[uid].keys.toList()[orderID]} : ${_currentOrders[uid].values.toList()[orderID]}',
style: TextStyle(fontSize: 16),
);
},
),
Padding(
padding: EdgeInsets.only(top: 10),
child: Container(
color: Colors.grey,
height: 1,
),
)
],
);
},
),
),
),
),
],
):Center(child: Text('No orders right now', style: TextStyle(fontSize: 30, color: Colors.black54),),);
}
);
Thank you.

Resources