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
2
Answers
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..
then inside the class I added this code above the build widget..
After adding that into the state I just declared each variable in the title of my ListTiles and it seemed to work
Make your
account.dart
a stateless widget, and try this code:-