how to retrieve phone number from firebase using flutter - firebase

How to retrieve phone number which is used during phone authentication in Firebase and display it using flutter, I tried this below method but it is not working for me:
FirebaseAuth.instance.currentUser().then((user) {
_userId = user.uid;
_phone = user.phoneNumber;
});
This is my full code
class HomePageState extends State<HomeScreen>{
String _userId,_phone;
#override
Widget build(BuildContext context) {
FirebaseAuth.instance.currentUser().then((user) {
_userId = user.uid;
_phone = user.phoneNumber;
});
var myGridView = new GridView.builder(
itemCount: services.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// childAspectRatio: (itemWidth / itemHeight),
),
itemBuilder: (BuildContext context, int index) {
return FlatButton(
child: Padding(
padding: const EdgeInsets.all(0.0),
// child:new Card(
//elevation: 5.0,
child: new Container(
alignment: Alignment.centerLeft,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Text(_userId),
],
),
),
),
),
onPressed: () {
String catgry = services[index];
if (catgry == "coming soon") {
showDialog(
barrierDismissible: false,
context: context,
child: new CupertinoAlertDialog(
title: new Column(
children: <Widget>[
new Text("This feature is coming soon"),
new Icon(
Icons.favorite,
color: Colors.red,
),
],
),
// content: new Text( services[index]),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: new Text("OK"))
],
));
} else {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Details(catgry,phone1)));
}
},
);
},
);
return new Scaffold(
appBar: new AppBar(
backgroundColor: Colors.black,
title: Text("Appbar", style: TextStyle(color: Colors.white),),
),),
body: myGridView,
bottomNavigationBar: CustomBottomBar(),
);
}
}

SInce you're using a StatefulWidget, you can create a getUser function that will update the userId and phone then call the Function in your initState. Also add a loading screen with Center(child: CircularProgressIndicator()) when fetching the values
class _HomeScreenState extends State<HomeScreen> {
String _userId,_phone;
bool loading = true;
getUser(){
FirebaseAuth.instance.currentUser().then((user) {
_userId = user.uid;
_phone = user.phoneNumber;
loading = false;
setState(() {});
});
}
#override
void initState() {
super.initState();
getUser();
}
#override
Widget build(BuildContext context) {
var myGridView = new GridView.builder(
itemCount: services.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// childAspectRatio: (itemWidth / itemHeight),
),
itemBuilder: (BuildContext context, int index) {
return FlatButton(
child: Padding(
padding: const EdgeInsets.all(0.0),
// child:new Card(
//elevation: 5.0,
child: new Container(
alignment: Alignment.centerLeft,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Text(_userId),
],
),
),
),
),
onPressed: () {
String catgry = services[index];
if (catgry == "coming soon") {
showDialog(
barrierDismissible: false,
context: context,
child: new CupertinoAlertDialog(
title: new Column(
children: <Widget>[
new Text("This feature is coming soon"),
new Icon(
Icons.favorite,
color: Colors.red,
),
],
),
// content: new Text( services[index]),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: new Text("OK"))
],
));
} else {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Details(catgry,phone1)));
}
},
);
},
);
return new Scaffold(
appBar: new AppBar(
backgroundColor: Colors.black,
title: Text("Appbar", style: TextStyle(color: Colors.white),),
),
body: loading?Center(child: CircularProgressIndicator()):myGridView,
bottomNavigationBar: CustomBottomBar(),
);
}
}

You can do this using async/await and once you get the data you can call setState()
String phone;
#override
void initState(){
super.initState();
getPhone();
}
getPhone() async{
FirebaseUser currentUser = await FirebaseAuth.instance.currentUser();
setState(() {
phone=currentUser.phoneNumber;
});
}

Related

firebase firestore chat timestamp order not working corectly

below is my code, i have a chat made in flutter and it should be sorted by timestamp however it is still seemingly random, on firebase it is recording the correct time stamp in json and i thought i had it coded correctly with the firestore.collection order by call. image attached shows the messages they should be ordered 1-6
import 'package:flutter/material.dart';
import 'package:bardsf/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
late String messageText;
class BodyBuildingChat extends StatefulWidget {
static const String id = 'body_building_chat';
#override
_BodyBuildingChatState createState() => _BodyBuildingChatState();
}
class _BodyBuildingChatState extends State<BodyBuildingChat> {
final messageTextController = TextEditingController();
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
late User loggedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print (e);
}
}
// void getMessages() async{
// final messages = await _firestore.collection('messages').get();
// for (var message in messages.docs) {
// print(message.data().cast());
// }
// }
void messagesStream() async {
await for( var snapshot in _firestore.collection('bodybuilding').orderBy('timestamp').snapshots()) {
for (var message in snapshot.docs) {
print(message.data().cast());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messagesStream();
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('🏔Body Building'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('bodybuilding').snapshots(),
builder: (context, snapshot){
List<MessageBubble> messageBubbles = [];
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data!.docs.reversed;
for (var message in messages) {
final messageText = message['text'];
final messageSender = message['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
children: messageBubbles,
),
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
TextButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('bodybuilding').add({
'text': messageText,
'sender': loggedInUser.email,
'timestamp': FieldValue.serverTimestamp(),
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({required this.sender,required this.text,required this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(sender,
style: TextStyle(
fontSize: 12.0,
),
),
Material(
borderRadius: isMe ? BorderRadius.only(topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
) : BorderRadius.only(topRight: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
child: Text('$text',
style: TextStyle( fontSize: 15.0,
color: isMe ? Colors.white : Colors.black,),
),
),
),
],
),
);
}
}
You did not use the appropriate stream.
Change this line
stream: _firestore.collection('bodybuilding').snapshots(),
into this line
stream: _firestore.collection('bodybuilding').orderBy('timestamp').snapshots(),
You will notice that you used the correct stream in the messagesStream but not in the StremBuilder.
Let me know if this does not help.

Problems with using a URL in NetworkImage (flutter)

I am trying to pass a URL that I receive from Firebase to my NetworkImage widget on the AppBar. However, my code keeps passing a null value to my NetworkImage widget. How can I pass the URL properly to the widget.
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
Future inputData() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseUser user = await auth.currentUser();
final uid = user.uid;
DocumentReference _stock = Firestore.instance.document('users/$uid');
DocumentSnapshot snapshot = await _stock.get();
Map<String, dynamic> data = snapshot.data;
return data['image_url'];
}
String myAvatarUrl;
void converter() {
inputData().then((result) {
myAvatarUrl = result;
print(myAvatarUrl);
});
}
#override
Widget build(BuildContext context) {
converter();
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 13.0),
child: CircleAvatar(
backgroundImage: NetworkImage(myAvatarUrl),
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchsettingsScreen(),
),
);
},
),
backgroundColor: Colors.white,
),
),
centerTitle: true,
title: Text(
'My Dashboard',
),
backgroundColor: Theme.of(context).primaryColor,
automaticallyImplyLeading: false,
actions: [
DropdownButton(
underline: Container(),
icon: Icon(
Icons.more_vert,
color: Theme.of(context).primaryIconTheme.color,
),
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: <Widget>[
Icon(
Icons.exit_to_app,
),
SizedBox(
width: 8.0,
),
Text('Logout'),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
},
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ReusableDashboardSettingCard(),
ReusableDashboardContactsCard(),
],
),
);
}
}
This is the error I get on my console:
The following assertion was thrown building DashboardScreen(dirty, state: _DashboardScreenState#e1615):
'package:flutter/src/painting/_network_image_io.dart': Failed assertion: line 26 pos 14: 'url != null': is not true.
Your main errors are:
you are not managing that there is the possibility that myAvatarUrl can be null
you are not telling to Flutter to rebuild your widget when data will arrive using setState((){})
I suggest you take a look at Codelabs and Fetch data from the internet.
I've not tested it but it should work
import 'package:flutter/material.dart';
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
String myAvatarUrl;
Future inputData() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseUser user = await auth.currentUser();
final uid = user.uid;
DocumentReference _stock = Firestore.instance.document('users/$uid');
DocumentSnapshot snapshot = await _stock.get();
Map<String, dynamic> data = snapshot.data;
return data['image_url'];
}
#override
void initState() {
super.initState();
// When data will arrive
inputData().then((value) {
setState(() => myAvatarUrl = value);
print(myAvatarUrl);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: myAvatarUrl == null
? const SizedBox()
: Padding(
padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 13.0),
child: CircleAvatar(
backgroundImage: NetworkImage(myAvatarUrl),
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchsettingsScreen(),
),
);
},
),
backgroundColor: Colors.white,
),
),
centerTitle: true,
title: Text(
'My Dashboard',
),
backgroundColor: Theme.of(context).primaryColor,
automaticallyImplyLeading: false,
actions: [
DropdownButton(
underline: Container(),
icon: Icon(
Icons.more_vert,
color: Theme.of(context).primaryIconTheme.color,
),
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: <Widget>[
Icon(
Icons.exit_to_app,
),
SizedBox(
width: 8.0,
),
Text('Logout'),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
},
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ReusableDashboardSettingCard(),
ReusableDashboardContactsCard(),
],
),
);
}
}

No such method error while calling a function

I retrieved products data from Firebase for my E-commerce homepage through future builder. I've created another screen that displays more information on a product when the user clicks on a product from the E-commerce homepage.To navigate to more information screen i created a function called showProduct and called it with a button, but when the button id pressed it shows
NoSuchMethodError: The method '[]' was called on null.Receiver: null Tried calling .
The showProduct function ] was also used on the vendor profile page where the products shown are shown in gridview and when clicked on any product from the vendors's profile.The showProduct function works and open more information screen.
E-commerce Homepage:
c
lass Shop extends StatefulWidget {
final Prod products;
final User currentUser;
final String prodId;
final String onwerId;
Shop({ this.currentUser,
this.prodId,
this.products,
this.onwerId});
#override
_ShopState createState() => _ShopState( prodId: this.prodId,products: this.products,ownerId:this.onwerId);
}
class _ShopState extends State<Shop> {
String postOrientation = "grid";
String shopOrientation = "grid";
bool isFollowing = false;
bool isLoading = false;
String uid="";
String prodId;
String ownerId;
Prod products;
_ShopState({
this.prodId, this.products,this.ownerId,
});
#override
void initState() {
super.initState();
showProduct;
}
Future getProducts()async {
var firestore = Firestore.instance;
QuerySnapshot snap = await firestore.collectionGroup("userProducts").getDocuments();
return snap.documents;
}
Future<Null>getRefresh()async{
await Future.delayed(Duration (seconds : 3));
setState(() {
getProducts();
});
}
showProduct(context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductScreen(
prodId: prodId,
userId: ownerId,
),
),
);
}
#override
Widget build(BuildContext context) {
return
Scaffold(
appBar: AppBar(backgroundColor: kSecondaryColor,
title: Text( 'Shop',
style: TextStyle(
fontFamily :"MajorMonoDisplay",
fontSize: 35.0 ,
color: Colors.white),),
iconTheme: new IconThemeData(color: kSecondaryColor),
),
backgroundColor: kPrimaryColor,
body:FutureBuilder(
future: getProducts(),
builder: (context,snapshot)
{
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: circularProgress(),);
} else {
return
RefreshIndicator(
onRefresh: getRefresh,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var ourdata = snapshot.data[index];
return
Container(
height: 500,
margin: EdgeInsets.only(
top: 1.0, left: 10.0, right: 10.0, bottom: 1.0),
child: Column( children: <Widget>[
SizedBox( height:1.0,),
Stack(
children: <Widget>[
Container(
child:Row(
children: <Widget>[
Expanded(
child: Container(
height: 400.0,
child: ClipRRect(borderRadius: BorderRadius.circular(20.0),
child: cachedNetworkImage(ourdata.data['shopmediaUrl'],
),
),
),
),
],
),
),
Expanded(
child: Positioned(
bottom: 10,
left: 10,
child: Container(
height: 40,
width: 40,
child: ClipRRect(
borderRadius: BorderRadius.circular(40.0),
child: Image.network(ourdata.data['photoUrl'],)),
),
),
),
Expanded(
child: Positioned(
bottom: 20,
left: 60,
child: Container(
child: Text(ourdata.data['username'],style: TextStyle(color: Colors.white,fontWeight:FontWeight.bold),),
),
),
),
Container(
alignment: Alignment.bottomRight,
child: GFButton(
onPressed: () => showProduct(context) ,
text: "More",
icon: Icon(Icons.card_travel),
shape: GFButtonShape.pills,
),
),
],
),
Row(
children: <Widget>[
Container(
child: Text(ourdata.data['productname'],style: TextStyle(color: kText,fontSize: 30.0,fontWeight:FontWeight.bold),),
),
],
),
Row(
children: <Widget>[
Container( child: Text('₹',style: TextStyle(color: kText,)),
),
Container(
child: Text(ourdata.data['price'],style: TextStyle(color: kText,fontSize: 20.0,fontWeight:FontWeight.bold),),
),
],
),
Divider(color: kGrey,),
],
),
);
}
)
);
}
}
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black38,
onPressed: ()
async{ Navigator.push(context, MaterialPageRoute(builder: (context) =>Uploadecom(currentUser: currentUser, )));
},
child: Icon(Icons.add_box),
),
);
}
}
This is the gridview on the vendor's profile.
class ProductTile extends StatelessWidget {
final Prod products;
ProductTile(this.products);
showProduct(context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductScreen(
prodId: products.prodId,
userId: products.ownerId,
),
),
);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => showProduct(context),
child: cachedNetworkImage(products.shopmediaUrl),
);
}
}
If you need more codes please ask me.

How to enable a button in Flutter,when dropdownbutton has value?

colleagues ! I'm noob in Flutter.This is my first app,and I'm trying to enable the button only when the user chooses a value from the dropdownbutton.
I was trying to find a similar question,but didn't find.
class Reserve extends StatefulWidget {
#override
_ReserveState createState() => _ReserveState();
}
class _ReserveState extends State<Reserve> {
var _category;
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
globals.salonname == "" ? "Reserve" : globals.salonname),
backgroundColor: Colors.deepOrange,
),
drawer: new Drawer(
child: new ListView(children: <Widget>[
new ListTile(
title: new Text("Close"),
trailing: new Icon(Icons.arrow_upward),
onTap: () {
Navigator.of(context).pop();
})
])),
body: Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Calendar(
isExpandable: true,
onDateSelected: null,
),
Row(children: <Widget>[
new Container(
alignment: Alignment(1.0, 0.0),
child: new Center(
child: new StreamBuilder<QuerySnapshot>
(
stream: Firestore.instance
.collection('salons').document(
globals.salonkey).collection(
'employee')
.snapshots(),
builder: (context, snapshot) {
try {
if
(snapshot.data.documents.length ==
0) {
return new Text("No employees
found!");
}
else {
return new DropdownButton(
hint: new Text(
"Choose an employee"),
items: snapshot.data.documents
.map(
(
DocumentSnapshot document) {
return DropdownMenuItem(
value: document
.data["name"],
child: new Text(
document
.data["name"]));
}).toList(),
value: _category,
onChanged: (value) {
setState(() {
_category = value;
});
});
}
}
catch (ex) {
return new Text("Try again!");
}
})),
)
]),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_buildButton(),
])
])))));
}
Widget _buildButton() {
return new RaisedButton(
padding: const EdgeInsets.all(8.0),
color: _category == true ? Colors.orangeAccent : Colors.grey,
child: Text("Choose employee"),
onPressed: _category==null ? null : () => setState(() => Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) =>
new ReserveTable()))));
}
}
So I want to enable the Raised button only,when an employee is chosen in dropdown button.
Thanks.
You will have to modify your code a little, if you need your button changes according to the Stream, move your StreamBuilder at your Column level and add a variable to check when the stream has data.
Here you have your code fixed:
class _ReserveState extends State<Reserve> {
var _category;
bool enableButton = false;
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:
new Text(globals.salonname == "" ? "Reserve" : globals.salonname),
backgroundColor: Colors.deepOrange,
),
drawer: new Drawer(
child: new ListView(children: <Widget>[
new ListTile(
title: new Text("Close"),
trailing: new Icon(Icons.arrow_upward),
onTap: () {
Navigator.of(context).pop();
})
])),
body: Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Form(
key: formKey,
child: new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('salons')
.document(globals.salonkey)
.collection('employee')
.snapshots(),
builder: (context, snapshot) {
return Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Calendar(
isExpandable: true,
onDateSelected: null,
),
Row(children: <Widget>[
new Container(
alignment: Alignment(1.0, 0.0),
child: new Center(
child: (!snapshot.hasData ||
snapshot.data.documents.length == 0)
? new Text("No employees found!")
: new DropdownButton(
hint:
new Text("Choose an employee"),
items: snapshot.data.documents.map(
(DocumentSnapshot document) {
return DropdownMenuItem(
value: document.data["name"],
child: new Text(
document.data["name"]));
}).toList(),
value: _category,
onChanged: (value) {
setState(() {
_category = value;
});
})))
]),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_buildButton(),
])
]);
})),
)));
}
Widget _buildButton() {
return new RaisedButton(
padding: const EdgeInsets.all(8.0),
color: _category!=null ? Colors.orangeAccent : Colors.grey,
child: Text("Choose employee"),
onPressed: _category==null
? null
: () => setState(() => Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) => ReserveTable()))));
}
}

Stream builder from firestore to flutter

I am wondering how to get data from firestore to flutter app using the streambuilder. I created the necessary Boilerplate code I have the widget built and working and in the below code
headimageassetpath is nothing but a URL string which exists in the firestore.
#override
Widget build(BuildContext context) {
return Scaffold(
body:
new StreamBuilder(
stream: Firestore.instance.collection('Items').snapshots(),
builder: (_, AsyncSnapshot<QuerySnapshot> snapshot) {
var items = snapshot.data?.documents ?? [];
return new Lost_Card(
headImageAssetPath : snapshot.data.documents.map()(['url'],)
);
},
)
My firestore:
full code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class LostPage extends StatefulWidget {
#override
_LostPage createState() => new _LostPage();
}
class _LostPage extends State<LostPage> {
//temp vars
final String firebasetest = "Test";
//firestore vars
final DocumentReference documentReference =
Firestore.instance.document("Items/Rusty");
//CRUD operations
void _add() {
Map<String, String> data = <String, String>{
"name": firebasetest,
"desc": "Flutter Developer"
};
documentReference.setData(data).whenComplete(() {
print("Document Added");
}).catchError((e) => print(e));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:
new StreamBuilder(
stream: Firestore.instance.collection('Items').snapshots(),
builder: (_, AsyncSnapshot<QuerySnapshot> snapshot) {
var items = snapshot.data?.documents ?? [];
return new Lost_Card(
headImageAssetPath : snapshot.data.documents.map()(['url'],)
);
},
)
/*new Lost_Card(
headImageAssetPath: "https://i.imgur.com/FtaGNck.jpg" ,
title: "Mega Dish",
noro: "old",
)*/,
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
onPressed: _add),
);
}
}
class Lost_Card extends StatelessWidget
{
//All the card variables
final String headImageAssetPath;
final IconData icon;
final Color iconBackgroundColor;
final String title;
final String noro;
final int price;
final ShapeBorder shape;
Lost_Card({
this.headImageAssetPath, //used
this.icon,
this.iconBackgroundColor,
this.title, //used
this.noro, //used
this.price,
});
#override
Widget build(BuildContext context) {
// TODO: implement build
return GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
children: <Widget>[
Card(
child: Column(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.height / 2.5,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
headImageAssetPath),
fit: BoxFit.cover),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: FractionalOffset.topLeft,
child: CircleAvatar(
backgroundColor: Colors.redAccent,
radius: 15.0,
child: Text(
noro,
textScaleFactor: 0.5,
),
),
),
),
Align(
alignment: FractionalOffset.topRight,
child: Container(
color: Colors.blueAccent,
height: 35.0,
width: 35.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.account_circle),
Text(
"1P",
textScaleFactor: 0.5,
),
],
),
),
),
),
],
),
),
Center(
child: Container(
padding: const EdgeInsets.all(8.0),
alignment: FractionalOffset.bottomCenter,
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.w700,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
child: Text(
"Add To Cart",
style: TextStyle(color: Colors.grey[500]),
),
onPressed: () => null,
),
Text(
"\$5",
style: TextStyle(color: Colors.grey[500]),
)
],
)
],
),
),
],
);
}
}
Actual App
Please shed some light on this. Tks.
This should work for one item
body: new StreamBuilder(
stream: Firestore.instance.collection("collection").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text(
'No Data...',
);
} else {
<DocumentSnapshot> items = snapshot.data.documents;
return new Lost_Card(
headImageAssetPath : items[0]["url"]
);
}
If you want to create list builder from many documents use it like this
return new ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.documents[index];
return new Lost_Card(
headImageAssetPath : ds["url"];
);
Accessing documents using StreamBuilder in Flutter 2
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('products').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot doc = snapshot.data!.docs[index];
return Text(doc['name']);
});
} else {
return Text("No data");
}
},
)
As per new changes 2021 in Firebase FireStore you can retrieve data from collection using StreamBuilder as below
final _mFirestore = FirebaseFirestore.instance;
return StreamBuilder<QuerySnapshot>(
stream:
_mFirestore.collection(kFirebaseCollectionName).snapshots(),
builder: (context, snapshots) {
if (!snapshots.hasData) {
return Center(
child: Text('Data not available',),
);
}
final messages = snapshots.data.docs;
List<Text> textWidgets = [];
messages.forEach((element) {
final messageText = element['text'];
final messageSender = element['sender'];
final textWidget = Text('$messageText, $messageSender');
textWidgets.add(messageBubbleWidget);
});
},
);
Card buildItem(DocumentSnapshot doc) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'name: ${doc.data['name']}',
style: TextStyle(fontSize: 24),
),
Text(
'todo: ${doc.data['todo']}',
style: TextStyle(fontSize: 20),
),
Text(
'Age: ${doc.data['age']}',
style: TextStyle(fontSize: 10),
),
SizedBox(
height: 12,
),
],
)
],
),
),
); }
For other persons who will face the same problem, the card and stream builder will represent a solution. The Widget has the Card just before it declaration and has inside the body the next part:
body: ListView(
padding: EdgeInsets.all(8),
children: <Widget>[
Form(
key: _formKey,
child: buildTextFormField(),
),
StreamBuilder<QuerySnapshot>(
stream: db
.collection('CRUD')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList());
} else {
return SizedBox();
}
},
)
],
),
Update for 2022, Flutter 2.10, cloud_firestore: ^3.1.11. You can retrieve data from collection using StreamBuilder
Stream collectionStream = FirebaseFirestore.instance.collection('users').snapshots();
StreamBuilder<QuerySnapshot>(
builder: (context, snapshot) {
if (snapshot.hasData) {
final messages = snapshot.data!.docs;
List<Text> messageWidgets = [];
for (var element in messages) {
final messageText = element['text'];
final messageSender = element['sender'];
final messageWidget =
Text('$messageText from $messageSender');
messageWidgets.add(messageWidget);
}
return Column(
children: messageWidgets,
);
}
return const Text('Error');
},
stream:collectionStream),
StreamBuilder<List<UData>>(
stream: AdminData().getDrivers,
builder: (context, snapshot) {
return ListView(
children: snapshot.data.map((document) {
return hadCard(
widget: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
hadText(title: document.name),
hadText(title: document.phone),
hadText(title: document.Driver),
],
),
);
}).toList(),
);
}),

Resources