Firebase Streambuilder - firebase

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.

Related

snapshot.data becomes null after half a second

I have a collection called pending_appointments and I want to access all of the documents which have the field patienduid equal to the current user's uid. Then there is a stream builder, but snapshots.data becomes null.
Like when I go to that screen, it shows me the expected results for about half a second and then it changes to 'No appointment found'.
Also, if I remove that 'where' statement, it shows me all the pending appointments which is the expect result, but as soon as I add the where statement which should give me the desired result, it goes back to no appointment after showing me the desired results for half a second.
Widget build(BuildContext context) {
return SafeArea(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('pending_appointments')
.where('patientUid', isEqualTo: user.uid)
.orderBy('date')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data != null) {
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.size,
itemBuilder: (context, index) {
DocumentSnapshot document = snapshot.data.docs[index];
print(_compareDate(document['date'].toDate().toString()));
if (_checkDiff(document['date'].toDate())) {
deleteAppointment(document.id);
}
return Card(
elevation: 2,
child: InkWell(
onTap: () {},
child: ExpansionTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Text(
'Dr. ${document['doctor']}',
style: GoogleFonts.lato(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
_compareDate(document['date'].toDate().toString())
? "TODAY"
: "",
style: GoogleFonts.lato(
color: Colors.green,
fontSize: 18,
fontWeight: FontWeight.bold),
),
SizedBox(
width: 0,
),
],
),
subtitle: Padding(
padding: const EdgeInsets.only(left: 5),
child: Text(
_dateFormatter(
document['date'].toDate().toString()),
style: GoogleFonts.lato(),
),
),
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 20, right: 10, left: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Patient name: " + document['name'],
style: GoogleFonts.lato(
fontSize: 16,
),
),
SizedBox(
height: 10,
),
Text(
"Time: " +
_timeFormatter(
document['date']
.toDate()
.toString(),
),
style: GoogleFonts.lato(
fontSize: 16,
),
),
],
),
IconButton(
tooltip: 'Delete Appointment',
icon: Icon(
Icons.delete,
color: Colors.black87,
),
onPressed: () {
print(">>>>>>>>>" + document.id);
_documentID = document.id;
showAlertDialog(context);
},
),
],
),
),
],
),
),
);
},
);
} else {
return Center(
child: Text(
'No Appointment Scheduled',
style: GoogleFonts.lato(
color: Colors.grey,
fontSize: 18,
),
),
);
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
remove this
if (snapshot.connectionState == ConnectionState.active) {
}
add this to your code
if (Snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (Snapshot.connectionState == ConnectionState.none) {
return Container();
}
if (Snapshot.data.docs.isEmpty) {
return Text(
'Document Empty',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
);
}
if (!Snapshot.hasData) {
return Text(
'0',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
);
}
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
final document = snapshot.data.docs[index].data();
print(_compareDate(document['date'].toDate().toString()));
if (_checkDiff(document['date'].toDate())) {
deleteAppointment(document.id);
}
});

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);
}

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,
);
},
),
),
),
);
}

Iterate over firebase database nodes flutter

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'
),
)
],
));
}),`

How to get data from other collection in streambuilder

I am facing a problem and I cannot solve it, I have a collection "Posts" that contain users' posts, each post contains a uid of the owner of the post, and I have another collection named "users", and each user has his name and photo, I want to get the user's name and image to display on his post.
Posts Collection
Users Collection
I have seen this article but I did not benefit perhaps because I am a beginner.
My Code:
StreamBuilder(
stream: Firestore.instance
.collection('Posts')
.orderBy('date', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
const Text('Loading...');
} else {
return ListView.builder(
physics:
NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapshot
.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot mypost =
snapshot
.data.documents[index];
return Stack(
children: <Widget>[
Container(
decoration:
BoxDecoration(
borderRadius:
BorderRadius
.circular(
15.0),
),
child: Padding(
padding:
EdgeInsets
.all(8.0),
child: Column(
children: <
Widget>[
InkWell(
child: Row(
children: <
Widget>[
Container(
width:
32.0,
height:
32.0,
decoration: BoxDecoration(shape: BoxShape.circle, image: DecorationImage(fit: BoxFit.fill, image: NetworkImage(
// user image url
'Owner of post img')))),
SizedBox(
width:
10.0,
),
Text(
'Owner of post Name',
style: TextStyle(
color: Colors.white,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'BalooDa2'),
),
],
),
),
Padding(
padding:
EdgeInsets.all(
5.0),
child: Text(
'${mypost['text']}',
style: TextStyle(
color: Colors
.white,
fontSize:
16.0,
fontFamily:
'Tajawal',
height:
1.3),
textAlign:
TextAlign
.justify,
textDirection:
TextDirection.rtl),
),
],
),
),
),
],
);
});
}
return Container(
height: 0.0,
width: 0.0,
);
},
),
You can user nested StreamBuilders to fetch user detail from the uid you are getting from posts collection.I have added a query which will match uid from posts data and look for the documents in users collection where uid is equal to uid from posts collection.
StreamBuilder(
stream: Firestore.instance
.collection('Posts')
.orderBy('date', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
const Text('Loading...');
} else {
return ListView.builder(
physics:
NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapshot
.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot mypost =
snapshot
.data.documents[index];
return Stack(
children: <Widget>[
Container(
decoration:
BoxDecoration(
borderRadius:
BorderRadius
.circular(
15.0),
),
child: Padding(
padding:
EdgeInsets
.all(8.0),
child: Column(
children: <
Widget>[
StreamBuilder(
stream: Firestore.instance
.collection('users')
.where('uid', isEqualTo: mypost['uid'])
.snapshots(),
builder: (context, snapshot){
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return SizedBox();
case ConnectionState.active:
default:
break;
}
if (snapshot.hasError) print(snapshot.error);
DocumentSnapshot user = snapshot.data.documents[0];
return InkWell(
child: Row(
children: <
Widget>[
Container(
width:
32.0,
height:
32.0,
decoration: BoxDecoration(shape: BoxShape.circle, image: DecorationImage(fit: BoxFit.fill, image: NetworkImage(
// user image url
'${user['uimg']}')))),
SizedBox(
width:
10.0,
),
Text(
'${user['name']}',
style: TextStyle(
color: Colors.white,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'BalooDa2'),
),
],
),
);
},
),
Padding(
padding:
EdgeInsets.all(
5.0),
child: Text(
'${mypost['text']}',
style: TextStyle(
color: Colors
.white,
fontSize:
16.0,
fontFamily:
'Tajawal',
height:
1.3),
textAlign:
TextAlign
.justify,
textDirection:
TextDirection.rtl),
),
],
),
),
),
],
);
});
}
return Container(
height: 0.0,
width: 0.0,
);
},
),

Resources