Fetch user data from firestore and show them in profile screen using flutter - firebase

The issue here is that when I fetch the data, I am suppose to fetch it for the current user but it is rather fetching data for all users within that collection.
I have done reading and watched a number of videos for a possible solution but I can't seem to find how to do this. Your help is needed please. Thanks.
A excerpt of the bode is below.
File image;
TextEditingController loginNameController = TextEditingController();
TextEditingController loginPhoneController = TextEditingController();
TextEditingController loginAddressController = TextEditingController();
clearForm() {
setState(() {
image = null;
loginNameController.clear();
loginPhoneController.clear();
loginAddressController.clear();
});
}
//=====> FOR INSTANCES OF FIREBASE <=====
final auth = FirebaseAuth.instance;
final db = FirebaseFirestore.instance;
User user = FirebaseAuth.instance.currentUser;
body: Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: StreamBuilder(
stream: db.collection("collection name").snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if (!snapshot.hasData) {
return Center(
child: spinkit,
);
}
return ListView.builder (
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index){
return Stack(
children: [
Column(
children: [
Stack(
children: [
// ===> RETRIEVING USER DETAILS AND SHOWING IT IN A ROW <===
Container(
padding : EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
backgroundColor: Palette.mainColor,
radius: 50,
child: ClipOval(
child: SizedBox(
height: 150,
width: 150,
child: image == null ? Center(
// child: Image.asset("asset/images/placeholder.png", fit: BoxFit.cover,),
child: Image.network(snapshot.data.documents[index].get("image")),
):
Image.file(image, fit: BoxFit.cover,),
),
),
),
SizedBox(width: 16,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 0),
child: Text(snapshot.data.documents[index].get("Name"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),),
),
SizedBox(height: 5,),
Text(snapshot.data.documents[index].get("Address"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black54,
fontSize: 16,
),),
SizedBox(height: 5,),
Text(snapshot.data.documents[index].get("Number"),
style: TextStyle(
letterSpacing: 2,
color: Colors.black54,
fontSize: 16,
),),
],
),
),
Padding(
padding: EdgeInsets.only(left: 0, bottom: 15),
child: IconButton(
icon:Icon(Icons.edit, color: Palette.mainColor, ),
onPressed: () { },
),
),
],
),
),
],
),
],
),
],
);
},
);
},
),
)
The collection name is members

Try like this, stream of your widget should be like this, as said above.
db.collection("Users").document(user.uid).snapshots();
for length in Listview.builder, change it too
snapshot.data.length;
And last, All the data which you fetch data like this should change into
from:
snapshot.data.documents[index].get("image")
To:
snapshot.data["image"]
Note I didn't test it. So, it might or might not work.

First of All use a DocumentSnapshot Shown below:
StreamBuilder<DocumentSnapshot>
Make a collection to get current user Profile data.
db.collection("Users").doc(user.uid).snapshots();
Remove ListView.builder
To get an Email Address use the below Line
Text('${streamSnapshot.data['Email Address']}'),
Here is the complete Article https://medium.com/#kamranktk807/fetch-user-data-from-firestore-and-show-them-in-profile-screen-using-flutter-609d2533e703
By the way I sol this problem with the help of a Professional Flutter Developer SHAKIR ZAHID [shakirzahid191#gmail.com].

Related

How to use Variables Cloud Firestore in Flutter (Dart) while doing query

This is my working code:
final Stream<QuerySnapshot> products = FirebaseFirestore.instance
.collection('products')
.doc('men')
.collection('tshirts')
.snapshots();
This is the code I want but not working:
String val = 'tshirts';
final Stream<QuerySnapshot> products = FirebaseFirestore.instance
.collection('products')
.doc('men')
.collection(val)
.snapshots();
Error: The instance member 'val' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression
The bellow code I am using in build widget to show database query results & working fine:
GridView.count(
physics: const BouncingScrollPhysics(),
crossAxisCount: 2,
childAspectRatio: 0.5,
mainAxisSpacing: 30,
crossAxisSpacing: 10,
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Visibility(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.bottomToTop,
child: const ProductView(productId: '3453245'),
));
},
child: Stack(
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('${data['img']}'),
fit: BoxFit.cover)),
),
Align(
alignment: Alignment.bottomLeft,
child: SizedBox(
height: 70,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(
right: 18, top: 15, left: 5),
child: Text(
data['name'].toUpperCase(),
textAlign: TextAlign.left,
style: GoogleFonts.oswald(
color: Colors.black,
fontSize: 15,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
),
),
Container(
margin: const EdgeInsets.only(left: 5),
child: Text(
'\u{20B9} ${data['price']}',
textAlign: TextAlign.left,
style: const TextStyle(
color: Colors.black,
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
)
],
),
).frosted(
blur: 7,
),
),
],
)),
visible: true,
);
}).toList(),
)
You are trying to use val before even initializing the class that is used.
You can only access it inside a method or the constructor, example:
#override
void initState() {
super.initState();
final Stream<QuerySnapshot> products = FirebaseFirestore.instance.collection('products').doc('men').collection(val).snapshots();
}

Error is not showing after scanning a item thats not on the firestore database

I did this personal project of mine where a barcode scanner would scan for data inside firestore database. I have this problem when I scanned a barcode thats not on the database it wont show the error message is just shows a empty scan item container which I made. Let me know if someone can figure why. I tried everything still couldnt fix it.
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("products")
.where("barcode", isEqualTo: '$barcodeScanRes')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Dialog(
child: Container(
height: 300,
child: Text('Product Not Found'),
),
);
} else {
return Dialog(
child: Container(
height: 350,
child: Column(children: [
Container(
height: 350,
width: 165,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot products =
snapshot.data!.docs[index];
return ScanCard(products: products);
},
)),
]),
),
);
#Scan Card
class ScanCard extends StatelessWidget {
const ScanCard({
Key? key,
required this.products,
}) : super(key: key);
final DocumentSnapshot products;
#override
Widget build(BuildContext context) {
final user = FirebaseAuth.instance.currentUser;
String _userId = user!.uid;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(10.0),
height: 180,
width: 160,
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.circular(16)),
child: Image.network(products['img']),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0 / 4),
child: Text(
products['name'],
style: TextStyle(
color: Colors.blueGrey,
fontSize: 18,
),
),
),
Column(
children: [
Text(
"Size: " + products['size'],
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.brown),
),
SizedBox(
width: 30,
),
],
),
Row(
children: [
Text(
"\tRs. " + products['price'],
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
SizedBox(
width: 40,
),
Icon(
Icons.add_shopping_cart,
color: Colors.black,
size: 25,
),
],
),
SizedBox(
width: 10,
),
SizedBox(
child: Padding(
padding: const EdgeInsets.all(10),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Colors.red,
child: Text(
"Add to cart",
style: TextStyle(color: Colors.white),
),
onPressed: () {
DocumentReference documentReference = FirebaseFirestore.instance
.collection('userData')
.doc(_userId)
.collection('cartData')
.doc();
documentReference.set({
'uid': FirebaseAuth.instance.currentUser!.uid,
'barcode': products['barcode'],
'img': products['img'],
'name': products['name'],
'size': products['size'],
'price': products['price'],
'id': documentReference.id
}).then((result) {
addToCartMessage(context).then((value) => {
Navigator.pop(context)
});
}).catchError((e) {
print(e);
});
},
),
),
)
],
);
}
}
The thing is you are showing Product not found based on the condition:- !snapshot.hasData but this conditon means that data is being fetched so at this time rather show a progress indicator.
And to handle when data is not present in backend then add another condition:- if(snapshot.data.docs.isEmpty) and here show your dialogbox of Product not found...
Final Code Snippet will look like:-
if (!snapshot.hasData)
return Center(child:CircularProgressIndicator));//or return a black container if you don't want to show anything while fetching data from firestore
else if (snapshot.data.docs.isEmpty) {
return Dialog(
child: Container(
height: 300,
child: Text('Product Not Found'),
),
);
} else {
return Dialog(
child: Container(
height: 350,
child: Column(children: [
Container(
height: 350,
width: 165,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot products =
snapshot.data!.docs[index];
return ScanCard(products: products);
},
)),
]),
),
);
}

how to fetch data from firestore array of a document with flutter?

this is my users collection in cloud fire store:
users collection
this is the function that gets users from users collection in firestore
Stream<QuerySnapshot> fetchUsersInSearch() {
return Firestore.instance.collection('users').snapshots();
}
i use this method
final emailResults = snapshot.data.documents
.where((u) => u['email'].contains(query));
in the following streamBuilder to fetch users by their email.
i have this streamBuilder to populate the data on screen
return StreamBuilder<QuerySnapshot>(
stream: DatabaseService().fetchUsersInSearch(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
final emailResults = snapshot.data.documents
.where((u) => u['email'].contains(query));
if (!snapshot.hasData) {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'',
style: TextStyle(
fontSize: 16, color: Theme.of(context).primaryColor),
),
),
);
}
if (emailResults.length > 0) {
return Container(
color: Theme.of(context).primaryColor,
child: ListView(
children: emailResults
.map<Widget>((u) => GestureDetector(
child: Padding(
padding: const EdgeInsets.all(0.1),
child: Container(
padding: EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border(
bottom: BorderSide(
width: 0.3, color: Colors.grey[50]))),
child: ListTile(
leading: CircleAvatar(
backgroundColor:
Theme.of(context).primaryColor,
backgroundImage:
NetworkImage(u['userAvatarUrl']),
radius: 20,
),
title: Container(
padding: EdgeInsets.only(left: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(u['email'],
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.accentColor),
overflow: TextOverflow.ellipsis),
SizedBox(
height: 5,
),
],
),
),
),
),
),
onTap: () {
showUserProfile(u['id']);
},
))
.toList(),
),
);
} else {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'No results found',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).accentColor,
),
),
),
);
}
});
this is working perfectly and fetching users inside a listView by their email...
p.s: the (query) is a string i type in a seach bar.
how can i make a query to fetch users by their otherUsernames...the second field in the screenshot of the users collection ?!
i tried this:
final otherUsernamesResults = snapshot.data.documents
.where((u) => u['otherUsernames'].contains(query));
but its returning this error:
The method 'contains' was called on null.
Receiver: null
Tried calling: contains("#username1")
what am i doing wrong here ?!!
any help would be much appreciated..
Try this:-
Stream<QuerySnapshot> getUsers() {
final usersCollection = FirebaseFirestore.instance.collection('users');
return usersCollection.where('otherUsernames', arrayContainsAny: ['username1', 'username2']);
}
For firestore version 0.16.0

Flutter Gridview button functionality to new screen with Firebase

I've made a Gridview using Firebase and Streambuilder and Gridview.builder. This grid displays album titles, the album cover art for each album, and the artists that make each album. I'd like for each grid tile to be able to be pressed and navigate to a separate page with its specific album details. The plan was on press, the app would be able to identify the entire document the grid tile was referring to, move to a new page, and display the document in full to unveil the album details. The thing is, I don't know how to do that. Since snapshot.data.documents[index]['Title'] worked when iterating though all the documents to create the gridview, I thought that typing snapshot.data.documents[index] would work, but it just displays Instance of 'DocumentSnapshot' in the debug console. I'm out of ideas on how to tackle this, so any suggestions are welcome
My code is shown below
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final Services services = Services();
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: bgcolour,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: Icon(Icons.menu),
title: Text("Home"),
actions: <Widget>[
Padding(padding: EdgeInsets.all(10), child: Icon(Icons.more_vert))
],
),
body: StreamBuilder(
stream: Firestore.instance.collection('music').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text("Loading...");
return GridView.builder(
itemCount: snapshot.data.documents.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, childAspectRatio: 0.655172413),
//cacheExtent: 1000.0,
itemBuilder: (BuildContext context, int index) {
var url = snapshot.data.documents[index]['Cover Art'];
return GestureDetector(
child: Container(
width: 190.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32)),
color: hexToColor(
snapshot.data.documents[index]['Palette'][0]),
elevation: 1,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(height: 12),
ClipRRect(
borderRadius: BorderRadius.circular(21.0),
child: Image.network(url,
height: 180.0, width: 180)),
SizedBox(height: 10),
Text(
snapshot.data.documents[index]['Artist']
.join(', '),
textAlign: TextAlign.center,
style: GoogleFonts.montserrat(
textStyle: TextStyle(color: Colors.white),
fontSize: 14,
fontWeight: FontWeight.w300)),
SizedBox(height: 10),
Text(snapshot.data.documents[index]['Title'],
style: GoogleFonts.montserrat(
textStyle: TextStyle(color: Colors.white),
fontSize: 16,
fontWeight: FontWeight.w600),
textAlign: TextAlign.center),
],
),
),
),
onTap: () {
print("Tapped ${snapshot.data.documents[index]}");
},
);
},
);
}
),
);
}
}
Is there an ID for your snapshot.data.documents[index]? If yes, add it to the end.
onTap: () {
print("Tapped ${snapshot.data.documents[index]['the property you want']}");
},

How can I get a subcollection on Firebase without specifying it?

Hey Guys I have these subcollections on my Firebase database under the "vocabulary" collection, but I would need to call them without specifying it, as they are more than one and they are called from the same page. Instead of the collection "colors", is it possible to not specify it as the "documentID" but for the collection?
class CategoryScreen extends StatelessWidget {
final DocumentSnapshot vocabulary;
CategoryScreen(this.vocabulary);
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<QuerySnapshot>(
future: Firestore.instance.collection('vocabulary').document(vocabulary.documentID)
.collection('colors').getDocuments(),
builder: (context, snapshot){
if(!snapshot.hasData)
return Center(
child: CircularProgressIndicator(),);
else
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Card(
elevation: 7.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)
),
child: Column(
children: <Widget>[
Container(
height: 350.0,
width: 350.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(vocabulary.data["image"]
),
fit: BoxFit.fill),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50)))
),
Container(
height: 70.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Center(
child: AutoSizeText(vocabulary.data["name"],
style: TextStyle(
fontFamily: 'Twiddlestix',
fontSize: 25,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
minFontSize: 15,
),
)
),
),
],
),
),
),
],
);
},
),
);
}
}
There are no wildcards in Cloud Firestore references to documents. So in order to create a query, you need to know all collection names. If you need to get only some documents within a collection based on a specific property, you'll have to do a query using some field value as a filter.
Instead of the collection "colors", is it possible to not specify it as the "documentID" but for the collection?
No, it's not possible. You cannot substitute that.

Resources