I am new to Flutter/Firebase/Firestore etc.. so I am struggling a bit. I want to grab the data from the documents in my ‘users’ collection in Firestore and display it in my account information page. I have spent hours messing around with this and I am stuck. If anybody could help me out that would be wonderful!
Here are some samples of what my code, app, and firestore look like.
Code:
signup.dart – this is the page that creates the doc in Firebase on signup
class SignUp extends StatefulWidget { const SignUp({Key? key}) : super(key: key); @override State<SignUp> createState() => _SignUpState(); } class _SignUpState extends State<SignUp> { var emailController = TextEditingController(); var passwordController = TextEditingController(); /* var docId = FirebaseFirestore.instance.collection('users').doc().id; */ final TextEditingController _usernameController = TextEditingController(); final TextEditingController _phoneNumberController = TextEditingController(); final TextEditingController _companyNameController = TextEditingController(); final FirebaseAuth auth = FirebaseAuth.instance; @override Widget build(BuildContext context) { String docId; docId = emailController.text; final User? user = auth.currentUser; double w = MediaQuery.of(context).size.width; double h = MediaQuery.of(context).size.height; return Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.white, body: Column( children: [ Container( width: w, height: h * 0.27, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/loginsignupheader.png"), fit: BoxFit.fitWidth, ), ), ), Container( margin: const EdgeInsets.only(left: 30, right: 20), width: w, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const Text( 'Sign up for an account', style: TextStyle(fontSize: 25, color: Colors.grey), ), const SizedBox(height: 35), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( blurRadius: 10, spreadRadius: 7, offset: const Offset(1, 1), color: Colors.grey.withOpacity(0.2)) ]), child: TextField( controller: _usernameController, decoration: InputDecoration( hintText: 'Username', prefixIcon: const Icon(Icons.person), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), ), ), ), ), const SizedBox(height: 35), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( blurRadius: 10, spreadRadius: 7, offset: const Offset(1, 1), color: Colors.grey.withOpacity(0.2)) ]), child: TextField( controller: _companyNameController, decoration: InputDecoration( hintText: 'Company Name', prefixIcon: const Icon(Icons.business_center), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), ), ), ), ), const SizedBox(height: 35), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( blurRadius: 10, spreadRadius: 7, offset: const Offset(1, 1), color: Colors.grey.withOpacity(0.2)) ]), child: TextField( controller: _phoneNumberController, decoration: InputDecoration( hintText: 'Phone Number', prefixIcon: const Icon(Icons.phone), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), ), ), ), ), const SizedBox(height: 35), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( blurRadius: 10, spreadRadius: 7, offset: const Offset(1, 1), color: Colors.grey.withOpacity(0.2)) ]), child: TextField( controller: emailController, decoration: InputDecoration( hintText: 'Email', prefixIcon: const Icon(Icons.email_outlined), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), ), ), ), ), const SizedBox(height: 35), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( blurRadius: 10, spreadRadius: 7, offset: const Offset(1, 1), color: Colors.grey.withOpacity(0.2)) ]), child: TextField( controller: passwordController, obscureText: true, decoration: InputDecoration( hintText: 'Password', prefixIcon: const Icon(Icons.password), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( color: Colors.white, width: 1.0)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), ), ), ), ), ], ), ), const SizedBox( height: 50, ), GestureDetector( onTap: () async { AuthController.instance.register( emailController.text.trim(), passwordController.text.trim()); FirebaseFirestore.instance.collection('users').doc(docId).set({ 'username': _usernameController.text, 'phone': _phoneNumberController.text, 'company_name': _companyNameController.text, 'email': emailController.text }); }, child: Container( width: w * .5, height: h * .06, decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), image: const DecorationImage( image: AssetImage("assets/button.png"), fit: BoxFit.cover, ), ), child: const Center( child: Text( 'Sign Up', style: TextStyle( fontSize: 30, fontWeight: FontWeight.bold, color: Colors.white), ), )), ), SizedBox(height: w * 0.1), RichText( text: TextSpan( text: "Already have an account?", style: const TextStyle(color: Colors.grey, fontSize: 20), children: [ TextSpan( text: " Login", style: const TextStyle( color: Colors.grey, fontSize: 20, fontWeight: FontWeight.bold), recognizer: TapGestureRecognizer() ..onTap = () { Navigator.push( context, MaterialPageRoute( builder: (context) => const Login())); }), ])), ], ), ); } }
account.dart – this is the page I want to display my Firestore data on
class Account extends StatefulWidget { const Account({Key? key}) : super(key: key); @override State<Account> createState() => _AccountState(); } class _AccountState extends State<Account> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey.shade50, body: Stack( fit: StackFit.expand, children: [ SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ const SizedBox(height: 10), const Text( 'Account Settings & Info', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black), ), Card( elevation: 2.0, margin: const EdgeInsets.fromLTRB(16, 8.0, 16, 16.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), child: Column( children: <Widget>[ const SizedBox(height: 20), Container( width: 75, height: 75, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(15), image: const DecorationImage(image: AssetImage('assets/tclogotransparent.png'), fit: BoxFit.cover) ), ), const SizedBox(height: 20), const BuildDivider(), ListTile( leading: const Icon( Icons.person, color: Colors.black, ), title: Text('Username: $username'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const ChangeEmail())); }, ), const BuildDivider(), ListTile( leading: const Icon( Icons.business_center, color: Colors.black, ), title: Text('Company Name: $companyName'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const ChangeEmail())); },), const BuildDivider(), ListTile( leading: const Icon( Icons.phone, color: Colors.black, ), title: Text('Phone Number: $phoneNumber'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const ChangeEmail())); }, ), const BuildDivider(), ListTile( leading: const Icon( Icons.email_outlined, color: Colors.black, ), title: Text('E-Mail: $emailAddress'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const ChangeEmail())); }, ), const BuildDivider(), ListTile( leading: const Icon( Icons.key, color: Colors.black, ), title: const Text('Change Password'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const ChangePassword())); }, ), const BuildDivider(), ListTile( leading: const Icon( Icons.upload, color: Colors.black, ), title: const Text('Upload Profile Picture'), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () { }, ), ], ), ), Card( color: Colors.red[50], elevation: 2.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), margin: const EdgeInsets.all(16), child: ListTile( onTap: () { AuthController.instance.signOut(); }, title: const Text('Log Out', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),), leading: const Icon(Icons.logout_outlined, color: Colors.red) ), ), ], ), ), ], ), ); } }
Firestore Docs – I want to take this data and display it in the account page shown below
Edit: I have the document ids being set as the users email, I wanted to try an easy way to recall the document per account. If this is wrong please let me know.
https://i.stack.imgur.com/53TOS.png
Account Page – These are the fields I want to fill with the data, they all say N/A because I have a separate temporary file that uses constants to set those values
https://i.stack.imgur.com/eoHUE.png
Edit: Edited account.dart throws a _CastError
https://i.stack.imgur.com/YRRz9.png
Advertisement
Answer
I have figured out the solution to my issue. In the _AccountState class I added the following lines of code and it seemed to work for me.
I added this above the _AccountState class..
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance
then inside the class I added this code above the build widget..
void _getData() async { User? user = _firebaseAuth.currentUser; FirebaseFirestore.instance.collection('users').doc(user?.email).snapshots().listen((userData) { setState(() { username = userData.data()!['username']; companyName = userData.data()!['company_name']; phoneNumber = userData.data()!['phone']; emailAddress = userData.data()!['email']; }); }); } @override void initState() { super.initState(); _getData(); }
After adding that into the state I just declared each variable in the title of my ListTiles and it seemed to work
ListTile( leading: const Icon( Icons.person, color: Colors.black, ), title: Text("Username: $username"), trailing: const Icon(Icons.keyboard_arrow_right), onTap: () {}, ),