I have my userData model as below:
class UserData {
String id;
String firstName;
String lastName;
String phoneNumber;
String streetAddress;
String city;
String state;
String postcode;
String country;
Timestamp createdAt;
Timestamp updatedAt;
UserData();
UserData.fromMap(Map<String, dynamic> data) {
id = data['id'];
firstName = data['first_name'];
lastName = data['last_name'];
phoneNumber = data['phone_number'];
streetAddress = data['street_address'];
city = data['city'];
postcode = data['postcode'];
state = data['state'];
country = data['country'];
createdAt = data['created_at'];
updatedAt = data['updated_at'];
}
Map<String, dynamic> toMap() {
return {
'id': id,
'first_name': firstName,
'last_name': lastName,
'phone_number': phoneNumber,
'street_address': streetAddress,
'city': city,
'postcode': postcode,
'state': state,
'country': country,
'created_at': createdAt,
'updated_at': updatedAt,
};
}
}
I have my Notifier class which I use to read and write userData to Firestore. Since this is userData, there will only be an instance per logged in user as they can only have one document holding their profile information.
class UserDataNotifier with ChangeNotifier {
UserData _currentLoggedInUserData;
Query userDataCollection = Firestore.instance.collection('userData');
UserData get currentLoggedInUserData => _currentLoggedInUserData;
set currentLoggedInUserData(UserData userData) {
_currentLoggedInUserData = userData;
notifyListeners();
}
getUserData(UserDataNotifier userDataNotifier) async {
String userId = (await FirebaseAuth.instance.currentUser()).uid;
await Firestore.instance.collection('userData').document(userId).get().then(
(value) => _currentLoggedInUserData = UserData.fromMap(value.data));
notifyListeners();
}
Future createOrUpdateUserData(UserData userData, bool isUpdating) async {
String userId = (await FirebaseAuth.instance.currentUser()).uid;
CollectionReference userDataRef = Firestore.instance.collection('userData');
if (isUpdating) {
userData.updatedAt = Timestamp.now();
await userDataRef.document(userId).updateData(userData.toMap());
print('updated userdata with id: ${userData.id}');
} else {
userData.createdAt = Timestamp.now();
DocumentReference documentReference = userDataRef.document(userId);
userData.id = documentReference.documentID;
await documentReference.setData(userData.toMap(), merge: true);
print('created userdata successfully with id: ${userData.id}');
}
notifyListeners();
}
}
How do I go about reading and displaying my userData in my profile screen?
Here's my Profile form screen:
class ProfileFormScreen extends StatefulWidget {
static const String id = 'profile_form';
#override
_ProfileFormScreenState createState() => _ProfileFormScreenState();
}
class _ProfileFormScreenState extends State<ProfileFormScreen> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
UserData _currentLoggedInUserData;
//global declarations
String selectedBusinessTypeDropDownValue = 'Fashion';
String selectedCountryDropDownValue = 'India';
String email;
bool showSpinner = false;
_saveUserData(BuildContext context) {
UserDataNotifier userNotifier =
Provider.of<UserDataNotifier>(context, listen: false);
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
userNotifier.createOrUpdateUserData(_currentLoggedInUserData, false);
Navigator.pop(context);
}
#override
void initState() {
super.initState();
UserDataNotifier userDataNotifier =
Provider.of<UserDataNotifier>(context, listen: false);
if (userDataNotifier.currentLoggedInUserData != null) {
_currentLoggedInUserData = userDataNotifier.currentLoggedInUserData;
print(_currentLoggedInUserData.id);
} else {
_currentLoggedInUserData = UserData();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Profile'),
),
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 20.0),
child: Form(
autovalidate: true,
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LabelTextPadding(text: 'Business Information'),
//location
RegularTextPadding(regText: 'Location'),
//address 1
_buildAddress(),
//city
_buildCityField(),
//postcode
_buildPostcode(),
//state
_buildStateField(),
//country
_buildCountry(),
SizedBox(
height: 20.0,
),
DividerClass(),
SizedBox(
height: 20.0,
),
//Personal information
LabelTextPadding(
text: 'Personal Information',
),
_buildFirstNameField(),
_buildLastNameField(),
_buildPhoneNumberField(),
_buildButtons(),
],
),
),
),
),
);
}
//business information
_buildAddress() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.streetAddress,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.streetAddress = value;
},
validator: TextInputFieldValidator.validate,
decoration:
kTextFieldDecoration.copyWith(hintText: 'house and street address'),
),
);
}
_buildCityField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.city,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.city = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter city'),
),
);
}
_buildPostcode() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.postcode,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.postcode = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter postcode'),
),
);
}
_buildStateField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.state,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.state = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter state'),
),
);
}
_buildCountry() {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(0.5)),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
),
),
padding: const EdgeInsets.fromLTRB(10.0, 10.0, 20.0, 0.0),
margin: EdgeInsets.all(20.0),
child: Center(
child: DropdownButton(
value: _currentLoggedInUserData.country == null
? selectedCountryDropDownValue
: _currentLoggedInUserData.country,
icon: Icon(
FontAwesomeIcons.caretDown,
color: kThemeStyleButtonFillColour,
),
elevation: 15,
underline: Container(
height: 0,
color: kThemeStyleButtonFillColour,
),
items: country
.map(
(country) =>
DropdownMenuItem(value: country, child: Text(country)),
)
.toList(),
onChanged: (newValue) {
setState(() {
selectedCountryDropDownValue = newValue;
_currentLoggedInUserData.country = newValue;
});
},
),
),
);
}
//user personal info build
_buildFirstNameField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.firstName,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.firstName = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'your first Name'),
),
);
}
_buildLastNameField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.lastName,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.lastName = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'your last name'),
),
);
}
_buildPhoneNumberField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.phoneNumber,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.phoneNumber = value;
},
validator: TextInputFieldValidator.validate,
decoration:
kTextFieldDecoration.copyWith(hintText: 'your phone number'),
),
);
}
_buildButtons() {
return Padding(
padding: const EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Buttons(
onPressedButton: () {
Navigator.pop(context);
},
buttonLabel: 'Cancel',
buttonColour: kThemeStyleButtonFillColour,
buttonTextStyle: kThemeStyleButton),
SizedBox(
width: 15.0,
),
Buttons(
onPressedButton: () => _saveUserData(context),
buttonLabel: 'Save',
buttonColour: kThemeStyleButtonFillColour,
buttonTextStyle: kThemeStyleButton),
],
),
);
}
}
class TextInputFieldValidator {
static String validate(String value) {
if (value.isEmpty) {
return 'This field can\'t be empty, you must enter a text';
}
if (value.length < 3) {
return 'You must enter at least a word';
}
}
}
Here's what I've tried:
getUserData(UserDataNotifier userDataNotifier) async {
String userId = (await FirebaseAuth.instance.currentUser()).uid;
await Firestore.instance.collection('userData').document(userId).get();
notifyListeners();
}
I think you would start by assigning a variable, like this:
var myVar = await Firestore.instance.collection('userData').document(userId).get();
var yourVariable = myVar.data()["YourFieldNameInFireStore"];
You might want to look into Provider or otherwise using ChangeNotifier.
An example for that from pieces of code, not tailored to your question and typed up here so possibly containing typos / missing information:
class Muser extends ChangeNotifier {
FirebaseUser firebaseUser;
// this example uses FirebaseAuth, not anything from FireStore,
// but you could easily add variables to your User class here such as
// userAge for example, which you could update in your getUserData method or something
fauth.User fAuthUser = fauth.FirebaseAuth.instance.currentUser;
Muser({
this.firebaseUser, this.userAge,
});
getUserData() {
}
int userAge;
Map<dynamic, int> _specialCalculatedUserInfo;
Map<dynamic, int> get specialCalculatedUserInfo{
if (_specialCalculatedUserInfo== null) {
_specialCalculatedUserInfo= _calculateUserInfo();
}
notifyListeners();
return _specialCalculatedUserInfo;
}
}
class ProfileViewState extends State<ProfileView> {
#override
void dispose() {
// TODO: implement dispose for controllers
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
Column(
children: <Widget>[
Text("Your Profile"),
Consumer<Muser>(
builder: (context, user, child) {
return
Column(
children: [
Text("Age: ${user.userAge}"),
CircleAvatar(
radius: 50,
backgroundColor: Colors.brown.shade600,
backgroundImage: user.firebaseUser.photoUri.isEmpty
? AssetImage("assets/images/icon.png")
: NetworkImage(user.getPhotoURL()),
),
],
);
}
)
]
)
);
}
}
Related
I am using Firebase and keep getting this annoying message when I click on the Login button :
flutter: 'package:firebase_auth/src/firebase_auth.dart': Failed assertion: line 487 pos 12: 'email != null': is not true.
The code works fine. The app is built and run successfully. This happens when I enter my email and password and click on the login button. Referred to these threads: https://github.com/flutter/flutter/issues/22028 , _AssertionError ('package:firebase_auth/src/firebase_auth.dart': Failed assertion: line 95 pos 12: 'email != null': is not true.) but none helped. Any help would be greatly appreciated:)
My code is:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Auth extends StatefulWidget {
#override
_AuthState createState() => _AuthState();
}
class _AuthState extends State<Auth> {
final _formKey = GlobalKey<FormState>();
final _password = TextEditingController(),
_email = TextEditingController(),
_phone = TextEditingController();
final _auth = FirebaseAuth.instance;
String email;
String password;
bool willLogin = true;
bool showPassword = false;
void _login() async {
_formKey.currentState.validate();
try {
final existingUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (existingUser != null) {
Navigator.pushNamed(context, '/home');
}
} catch (e) {
print(e);
}
}
void _signup() async {
_formKey.currentState.validate();
try {
final newUser = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
if (newUser != null) {
Navigator.pushNamed(context, '/home');
}
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dog SOS"),
leading: Icon(Icons.pets),
),
body: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(24),
children: [
const SizedBox(
height: 10,
),
Center(
child: CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
child: Icon(
Icons.shield,
color: Colors.white,
size: 50,
),
radius: 60,
),
),
const SizedBox(
height: 20,
),
if (!willLogin) ...[
TextFormField(
decoration: InputDecoration(
labelText: "Phone",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
controller: _phone,
validator: (value) =>
value.isEmpty ? "Please Enter Phone Number" : null,
),
const SizedBox(
height: 10,
),
],
TextFormField(
decoration: InputDecoration(
labelText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
controller: _email,
validator: (value) => value.isEmpty ? "Please Enter Email" : null,
),
const SizedBox(
height: 10,
),
TextFormField(
decoration: InputDecoration(
labelText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
suffixIcon: IconButton(
icon: Icon(
showPassword
? Icons.visibility_off_outlined
: Icons.visibility_outlined,
),
onPressed: () {
setState(() {
showPassword = !showPassword;
});
},
),
),
obscureText: !showPassword,
textInputAction: TextInputAction.done,
controller: _password,
validator: (value) =>
value.isEmpty ? "Please Enter Password" : null,
),
const SizedBox(
height: 10,
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Text(
willLogin ? "\nLOGIN\n" : "\nSIGN UP\n",
style: Theme.of(context)
.textTheme
.button
.copyWith(color: Colors.white),
),
color: Theme.of(context).primaryColor,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
_login();
}
},
),
Row(
children: [
Text(willLogin
? "Don't have an account?"
: "Already have an account?"),
FlatButton(
child: Text(
willLogin ? "Create One." : "Login.",
style: Theme.of(context).textTheme.button.copyWith(
color: Theme.of(context).primaryColor,
),
),
onPressed: () {
setState(() {
willLogin = !willLogin;
_signup();
});
},
),
],
),
],
),
),
);
}
}
String email;
String password;
Both of those are null, they are not referencing anything. You have to do the following, first bind the controller to the field which you are already doing then:
void _login() async {
_formKey.currentState.validate();
try {
final existingUser = await _auth.signInWithEmailAndPassword(
email: _email.text, password: _password.text);
if (existingUser != null) {
Navigator.pushNamed(context, '/home');
}
} catch (e) {
print(e);
}
}
Use the property text of the class TextEditingController to get the value of _email and _password.
I'm trying to read my UserData into form fields when the user tried to edit their information. I can write to Firebase, but I can't read and display user data into the built fields. Each userData is stored with the signed in user's mid as the userData's id, for distinctiveness.
What am I missing? See below for what I've attempted.
Here's my UserData model:
class UserData {
String id;
String firstName;
String lastName;
String phoneNumber;
String role;
String businessName;
String businessType;
String streetAddress;
String city;
String state;
String postcode;
String country;
String businessTradingCurrency;
Timestamp createdAt;
Timestamp updatedAt;
UserData(
this.id,
this.firstName,
this.businessTradingCurrency,
this.businessType,
this.businessName,
this.city,
this.country,
this.createdAt,
this.lastName,
this.phoneNumber,
this.postcode,
this.role,
this.state,
this.streetAddress,
this.updatedAt,
);
UserData.fromMap(Map<String, dynamic> data) {
id = data['id'];
firstName = data['first_name'];
lastName = data['last_name'];
phoneNumber = data['phone_number'];
businessTradingCurrency = data['trading_currency'];
role = data['role'];
businessName = data['business_name'];
businessType = data['business_type'];
streetAddress = data['street_address'];
city = data['city'];
postcode = data['postcode'];
state = data['state'];
country = data['country'];
createdAt = data['created_at'];
updatedAt = data['updated_at'];
}
Map<String, dynamic> toMap() {
return {
'id': id,
'first_name': firstName,
'last_name': lastName,
'phone_number': phoneNumber,
'role': role,
'trading_currency': businessTradingCurrency,
'business_name': businessName,
'business_type': businessType,
'street_address': streetAddress,
'city': city,
'postcode': postcode,
'state': state,
'country': country,
'created_at': createdAt,
'updated_at': updatedAt,
};
}
}
Here's my UserData notifier class:
class UserDataNotifier with ChangeNotifier {
UserData _currentLoggedInUserData;
CollectionReference userDataRef = Firestore.instance.collection('userData');
UserData get currentLoggedInUserData => _currentLoggedInUserData;
set currentLoggedInUserData(UserData userData) {
_currentLoggedInUserData = userData;
notifyListeners();
}
Future<void> getUserData() async {
String userId = (await FirebaseAuth.instance.currentUser()).uid.toString();
DocumentSnapshot result =
await Firestore.instance.collection('userData').document(userId).get();
_currentLoggedInUserData = result.data as UserData;
print('Phone Number: ${_currentLoggedInUserData.phoneNumber}');
notifyListeners();
}
Future createOrUpdateUserData(UserData userData, bool isUpdating) async {
String userId = (await FirebaseAuth.instance.currentUser()).uid;
if (isUpdating) {
userData.updatedAt = Timestamp.now();
await userDataRef.document(userId).updateData(userData.toMap());
print('updated userdata with id: ${userData.id}');
} else {
userData.createdAt = Timestamp.now();
DocumentReference documentReference = userDataRef.document(userId);
userData.id = documentReference.documentID;
await documentReference.setData(userData.toMap(), merge: true);
print('created userdata successfully with id: ${userData.id}');
}
notifyListeners();
}
}
Here's my Edit User Profile Form:
class ProfileFormScreen extends StatefulWidget {
static const String id = 'profile_form';
#override
_ProfileFormScreenState createState() => _ProfileFormScreenState();
}
class _ProfileFormScreenState extends State<ProfileFormScreen> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
UserData _currentLoggedInUserData;
bool showSpinner = false;
//global declarations
String selectedBusinessTypeDropDownValue = 'Fashion';
String selectedCurrencyDropDownValue = 'AUD: Australian Dollar';
String selectedCountryDropDownValue = 'Australia';
String email;
#override
void initState() {
super.initState();
UserDataNotifier userDataNotifier =
Provider.of<UserDataNotifier>(context, listen: false);
if (userDataNotifier.currentLoggedInUserData != null) {
_currentLoggedInUserData = userDataNotifier.currentLoggedInUserData;
} else {
_currentLoggedInUserData = UserData(
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
);
}
}
#override
Widget build(BuildContext context) {
UserDataNotifier userDataNotifier =
Provider.of<UserDataNotifier>(context, listen: false);
print('Logged in user id: ${_currentLoggedInUserData.id}');
_saveUserData() async {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
userDataNotifier.createOrUpdateUserData(_currentLoggedInUserData, true);
Navigator.pop(context);
}
return Scaffold(
appBar: AppBar(
title: Text('Edit Profile'),
actions: <Widget>[
FlatButton(
onPressed: () => _saveUserData(),
child: Icon(
FontAwesomeIcons.save,
color: kThemeStyleButtonFillColour,
)),
],
),
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: SingleChildScrollView(
// padding: EdgeInsets.only(top: 20.0),
child: Form(
autovalidateMode: AutovalidateMode.always,
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LabelTextPadding(text: 'Business Information'),
//business name
RegularTextPadding(regText: 'Business Name'),
_buildBusinessName(),
SizedBox(height: 20.0),
//business type
RegularTextPadding(regText: 'Business Type'),
Platform.isIOS
? _buildCupertinoStyleBusinessType(context)
: _buildMaterialStyleBusinessType(context),
//Trading currency
RegularTextPadding(regText: 'Trading Currency'),
Platform.isIOS
? _buildCupertinoStyleTradingCurrency(context)
: _buildMaterialStyleTradingCurrency(context),
//business location
RegularTextPadding(regText: 'Location'),
//address 1
_buildAddress(),
//city
_buildCityField(),
//postcode
_buildPostcode(),
//state
_buildStateField(),
//country
Platform.isIOS
? _buildCupertinoStyleCountry(context)
: _buildMaterialStyleCountry(context),
SizedBox(
height: 20.0,
),
DividerClass(),
SizedBox(
height: 20.0,
),
//Personal information
LabelTextPadding(
text: 'Personal Information',
),
_buildFirstNameField(),
_buildLastNameField(),
_buildPhoneNumberField(),
// _buildEmailField(),
//cancel and save buttons
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Buttons(
onPressedButton: () {
Navigator.pop(context);
},
buttonLabel: 'Cancel',
buttonColour: kThemeStyleButtonFillColour,
buttonTextStyle: kThemeStyleButton),
SizedBox(
width: 15.0,
),
Buttons(
onPressedButton: () => _saveUserData(),
buttonLabel: 'Save',
buttonColour: kThemeStyleButtonFillColour,
buttonTextStyle: kThemeStyleButton),
],
),
),
],
),
),
),
),
);
}
//business information
Widget _buildBusinessName() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.businessName,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.businessName = value;
},
validator: TextInputFieldValidator.validate,
decoration:
kTextFieldDecoration.copyWith(hintText: 'update business Name'),
),
);
}
//business type - cupertino and material styles
_buildCupertinoStyleBusinessType(BuildContext context) {
return GestureDetector(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
)),
padding: const EdgeInsets.fromLTRB(10.0, 12.0, 10.0, 12.0),
margin: EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(selectedBusinessTypeDropDownValue),
Icon(
FontAwesomeIcons.caretDown,
color: kThemeStyleButtonFillColour,
),
],
),
),
onTap: () => showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
color: Colors.white,
height: MediaQuery.of(context).copyWith().size.height / 4,
child: CupertinoPicker(
magnification: 1.5,
children: List<Widget>.generate(businessType.length, (int index) {
return Center(
child: Text(
businessType[index].toString(),
softWrap: true,
style: TextStyle(fontSize: 15.0),
),
);
}),
itemExtent: 25,
onSelectedItemChanged: (index) {
setState(() {
selectedBusinessTypeDropDownValue = businessType[index];
});
},
),
);
},
),
);
}
_buildMaterialStyleBusinessType(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
)),
margin: EdgeInsets.all(20.0),
width: MediaQuery.of(context).size.width,
child: Center(
child: DropdownButton(
value: _currentLoggedInUserData.businessType == null
? selectedBusinessTypeDropDownValue
: _currentLoggedInUserData.businessType,
elevation: 15,
iconDisabledColor: kThemeStyleButtonFillColour,
iconEnabledColor: kThemeStyleButtonFillColour,
underline: Container(),
items: businessType
.map(
(businessType) => DropdownMenuItem(
value: businessType, child: Text(businessType)),
)
.toList(),
onChanged: (newValue) {
setState(() {
selectedBusinessTypeDropDownValue = newValue;
_currentLoggedInUserData.businessType = newValue;
});
},
),
),
);
}
//trading currency - cupertino and material styles
_buildCupertinoStyleTradingCurrency(BuildContext context) {
return GestureDetector(
onTap: () => showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
color: Colors.white,
height: MediaQuery.of(context).copyWith().size.height / 4,
child: CupertinoPicker(
magnification: 1.5,
children:
List<Widget>.generate(tradingCurrency.length, (int index) {
return Center(
child: Text(
tradingCurrency[index].toString(),
softWrap: true,
style: TextStyle(fontSize: 15.0),
),
);
}),
itemExtent: 25,
onSelectedItemChanged: (index) {
setState(() {
selectedCurrencyDropDownValue = tradingCurrency[index];
});
},
),
);
},
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(0.5)),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
)),
padding: const EdgeInsets.fromLTRB(10.0, 12.0, 10.0, 12.0),
margin: EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(selectedCurrencyDropDownValue),
Icon(
FontAwesomeIcons.caretDown,
color: kThemeStyleButtonFillColour,
),
],
),
),
);
}
_buildMaterialStyleTradingCurrency(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
)),
margin: EdgeInsets.all(20.0),
width: MediaQuery.of(context).size.width,
child: Center(
child: DropdownButton(
value: _currentLoggedInUserData.businessType == null
? selectedCurrencyDropDownValue
: _currentLoggedInUserData.businessTradingCurrency,
icon: Icon(
FontAwesomeIcons.caretDown,
color: kThemeStyleButtonFillColour,
),
elevation: 15,
underline: Container(
color: kThemeStyleButtonFillColour,
),
items: tradingCurrency
.map(
(tradingCurrency) => DropdownMenuItem(
value: tradingCurrency, child: Text(tradingCurrency)),
)
.toList(),
onChanged: (newValue) {
setState(() {
selectedCurrencyDropDownValue = newValue;
_currentLoggedInUserData.businessTradingCurrency = newValue;
});
},
),
),
);
}
//address field
_buildAddress() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.streetAddress,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.streetAddress = value;
},
validator: TextInputFieldValidator.validate,
decoration:
kTextFieldDecoration.copyWith(hintText: 'house and street address'),
),
);
}
//city field
_buildCityField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.city,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.city = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter city'),
),
);
}
//postcode field
_buildPostcode() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.postcode,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.postcode = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter postcode'),
),
);
}
//state field
_buildStateField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.state,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.state = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'enter state'),
),
);
}
//country field - cupertino and material styles
_buildCupertinoStyleCountry(BuildContext context) {
return GestureDetector(
onTap: () => showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
color: Colors.white,
height: MediaQuery.of(context).copyWith().size.height / 4,
child: CupertinoPicker(
magnification: 1.5,
children: List<Widget>.generate(country.length, (int index) {
return Center(
child: Text(
country[index].toString(),
softWrap: true,
style: TextStyle(fontSize: 15.0),
),
);
}),
itemExtent: 25,
onSelectedItemChanged: (index) {
setState(() {
selectedCountryDropDownValue = country[index];
});
},
),
);
},
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(0.5)),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
),
),
padding: const EdgeInsets.fromLTRB(10.0, 12.0, 20.0, 12.0),
margin: EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(selectedCountryDropDownValue),
Icon(
FontAwesomeIcons.caretDown,
color: kThemeStyleButtonFillColour,
),
],
),
),
);
}
_buildMaterialStyleCountry(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: kThemeStyleButtonFillColour,
width: 1,
),
),
margin: EdgeInsets.all(20.0),
width: MediaQuery.of(context).size.width,
child: Center(
child: DropdownButton(
value: _currentLoggedInUserData.country == null
? selectedCountryDropDownValue
: _currentLoggedInUserData.country,
elevation: 15,
iconDisabledColor: kThemeStyleButtonFillColour,
iconEnabledColor: kThemeStyleButtonFillColour,
underline: Container(),
items: country
.map(
(country) =>
DropdownMenuItem(value: country, child: Text(country)),
)
.toList(),
onChanged: (newValue) {
setState(() {
selectedCountryDropDownValue = newValue;
_currentLoggedInUserData.country = newValue;
});
},
),
),
);
}
//logged in user personal info build
//first name
_buildFirstNameField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.firstName,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.firstName = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'your first Name'),
),
);
}
//last name
_buildLastNameField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.lastName,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.lastName = value;
},
validator: TextInputFieldValidator.validate,
decoration: kTextFieldDecoration.copyWith(hintText: 'your last name'),
),
);
}
//phone number
_buildPhoneNumberField() {
return Container(
padding: EdgeInsets.all(20.0),
child: TextFormField(
initialValue: _currentLoggedInUserData.phoneNumber,
textAlign: TextAlign.left,
onSaved: (value) {
_currentLoggedInUserData.phoneNumber = value;
},
validator: TextInputFieldValidator.validate,
decoration:
kTextFieldDecoration.copyWith(hintText: 'your phone number'),
),
);
}
}
class TextInputFieldValidator {
static String validate(String value) {
if (value.isEmpty) {
return 'This field can\'t be empty, you must enter a text';
}
if (value.length < 3) {
return 'You must enter at least a word';
}
return value;
}
}
I am using the method createUserWithEmailAndPassword but would like to collect more data when a user signs up. In addition to email and password I would also like to collect:
First Name
Last Name
Date of Birth
Here is my auth services code:
//Email & Password Sign Up
Future<String> createUserWithEmailAndPassword(
String email, String password,
) async {
final authResult = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// Update the username
await updateUserName(email, authResult.user);
return authResult.user.uid;
}
and my sign up page:
import 'package:easy_tiger/constants/appbar.dart';
import 'package:easy_tiger/screens/account.dart';
import 'package:easy_tiger/style.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:easy_tiger/services/auth_service.dart';
enum AuthFormType { signIn, signUp }
class SignUpPage extends StatefulWidget {
final AuthFormType authFormType;
SignUpPage({Key key, this.authFormType}) : super(key: key);
#override
_SignUpPageState createState() => _SignUpPageState(authFormType: this.authFormType);
}
class _SignUpPageState extends State<SignUpPage> {
AuthFormType authFormType;
_SignUpPageState({this.authFormType});
final formKey = GlobalKey<FormState>();
String _firstName,
_lastName,
_email,
_confirmEmail,
_password,
_confirmPassword,
_dateOfBirth;
bool validate(){
final form = formKey.currentState;
form.save();
if(form.validate()){
form.save();
return true;
} else {
return false;
}
}
void switchFormState(String state) {
formKey.currentState.reset();
formKey.currentState.validate();
if(state == 'signUp') {
setState(() {
authFormType = AuthFormType.signUp;
});
} else {
setState(() {
authFormType = AuthFormType.signIn;
});
}
}
void submit() async {
if (validate()) {
try {
final auth = Provider
.of(context)
.auth;
if (authFormType == AuthFormType.signIn) {
String uid = await auth.signInWithEmailAndPassword(_email, _password);
print("Signed In with ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
} else {
String uid = await auth.createUserWithEmailAndPassword(
_email,
_password,);
print("Signed up with New ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
}
} catch (e) {
print(e);
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(80),
child: MainAppBar(
text: buildAppBarText(),
)),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Center(
child: Container(
child: Column(
children: <Widget>[
Align(
child: Text(buildTitleText(), style: AppBarTextStyle),
),
Container(
padding: EdgeInsets.only(top: 10),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
key: formKey,
child: Column(
children: buildInputs() + buildSwitchText(),
)),
),
],
),
),
),
),
));
}
buildHeaderText() {
String _headerText;
if (authFormType == AuthFormType.signUp) {
_headerText = "Don't have an account?";
} else {
_headerText = "Already have an account?";
} return _headerText;
}
List<Widget> buildInputs() {
List<Widget> textFields = [];
if (authFormType == AuthFormType.signIn) {
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Email'),
validator: EmailValidator.validate,
onSaved: (value) => _email = value
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Password'),
obscureText: true,
validator: PasswordValidator.validate,
onSaved: (value) => _password = value,
),);
}
else {
textFields.clear();
//if we're in the sign up state, add name
// add email & password
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('First Name'),
onSaved: (value) => _firstName,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Last Name'),
onSaved: (value) => _lastName,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Email Address'),
onSaved: (value) => _email,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Confirm Email Address'),
onSaved: (value) => _confirmEmail,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Password'),
obscureText: true,
onSaved: (value) => _password,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Confirm Password'),
onSaved: (value) => _confirmPassword,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Date of Birth'),
onSaved: (value) => _dateOfBirth,
));
textFields.add(SizedBox(
height: 15,
));
}
return textFields;
}
List<Widget> buildSwitchText() {
String _switchButtonTextPart1, _switchButtonTextPart2,_newFormState;
if(authFormType == AuthFormType.signIn) {
_switchButtonTextPart1 = "Haven't got an account? ";
_switchButtonTextPart2 = 'Sign Up';
_newFormState = 'signUp';
} else {
_switchButtonTextPart1 = 'Already have an account? ';
_switchButtonTextPart2 = 'Sign In';
_newFormState = 'signIn';
} return [
SizedBox(height: 5.0),
Container(
width: MediaQuery.of(context).size.height * 0.7,
child: RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0),),
color: kPrimaryColor,
textColor: Colors.black,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(buildTitleText(),
style: TextStyle(fontFamily: FontNameDefault,
fontSize: 15.0),),
),
onPressed: submit),
),
SizedBox(height: 5.0,),
RichText(
text: TextSpan(
style: TextStyle(
fontFamily: FontNameDefault,
color: Colors.black,
fontSize: 12.0,
),
children: <TextSpan>[
TextSpan(
text: _switchButtonTextPart1
),
TextSpan(
text: _switchButtonTextPart2,
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.black,
fontSize: 12.0),
recognizer: TapGestureRecognizer()
..onTap = () {
switchFormState(_newFormState);
})
]),
),
];
}
String buildAppBarText() {
String _switchAppBarHeader;
if(authFormType == AuthFormType.signIn) {
_switchAppBarHeader = "Already have an account?";
} else {
_switchAppBarHeader = "Don't have an account?";
} return
_switchAppBarHeader;
}
String buildTitleText() {
String _switchTextHeader;
if(authFormType == AuthFormType.signIn) {
_switchTextHeader = "Sign In";
} else {
_switchTextHeader = "Sign Up";
} return
_switchTextHeader;
}
}
class AccountController extends StatelessWidget {
#override
Widget build(BuildContext context) {
final AuthService auth = Provider.of(context).auth;
return StreamBuilder(
stream: auth.onAuthStateChanged,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final bool signedIn = snapshot.hasData;
return signedIn ? SignInPage() : SignUpPage();
}
return CircularProgressIndicator();
});
}
}
InputDecoration buildSignUpInputDecoration(String hint) {
return InputDecoration(
isDense: true,
fillColor: Colors.white,
hintText: hint,
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 0.0),
),
contentPadding: const EdgeInsets.only(left: 14.0, bottom: 10.0, top: 10.0),
);
}
class Provider extends InheritedWidget {
final AuthService auth;
Provider({Key key, Widget child, this.auth}) : super(key: key, child: child);
#override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static Provider of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<Provider>();
}
Can someone advise the best way to go about achieving this thanks.
Managed to work out a solution...
In my signup screen I imported cloud_firestore:
import 'package:cloud_firestore/cloud_firestore.dart';
I then altered the following to use the uid we create to create a document and set the fields equal to the values passed:
if (validate()) {
try {
final auth = Provider
.of(context)
.auth;
if (authFormType == AuthFormType.signIn) {
String uid = await auth.signInWithEmailAndPassword(_email, _password);
print("Signed In with ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
} else {
String uid = await auth.createUserWithEmailAndPassword(
_email,
_password,);
userCollection.document(uid).setData({
'First Name' : _firstName,
'Last Name' : _lastName,
'Date of Birth' : _dateOfBirth
});
print("Signed up with New ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
}
} catch (e) {
print(e);
}
I had to remove my validation method as it was causing issues. Ran the new code and a new user appeared in my database.
you will save the addition data inside your firestore e.g(firstname, lastname, date of birth) and add extra field for user id which will identify/mapped/linked the user with the firebaseAuth data
you will get the data(uid) from the AuthResult.user object.
When user registration, authentication occurred but not added data to the firebase that asking while signup such as registration number, Name, and TP no, etc. in flutter. So, what's wrong with my code?
Below one is the code for signup_view.dart file
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:uocportal/provider_widget.dart';
import 'package:uocportal/auth_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
//import 'package:auto_size_text/auto_size_text.dart';
enum AuthFormType { signIn, signUp, reset }
class SignUpView extends StatefulWidget {
final AuthFormType authFormType;
SignUpView({Key key, #required this.authFormType}) : super(key: key);
#override
_SignUpViewState createState() =>
_SignUpViewState(authFormType: this.authFormType);
}
class _SignUpViewState extends State<SignUpView> {
AuthFormType authFormType;
_SignUpViewState({this.authFormType});
var reNumFieldController = new TextEditingController();
final formKey = GlobalKey<FormState>();
String
_email,
_password,
_name,
_regnumber,
_faculty,
_contact,
_warning;
final _userCollectionReference = Firestore.instance;
// prefs.setString('stringRegnumValue', _regnumber);
Future createUser() async {
try {
final prefs = await SharedPreferences.getInstance();
prefs.setString('my_regno_key', _regnumber.toString());
await _userCollectionReference
.collection('Users')
.document()
.setData({
'username': _name,
'email': _email,
'contact': _contact,
'faculty': _faculty,
'regnumber': _regnumber
});
} catch (e) {
return e.message;
}
}
void switchFormState(String state) {
formKey.currentState.reset();
if (state == "signUp") {
setState(() {
authFormType = AuthFormType.signUp;
});
} else {
setState(() {
authFormType = AuthFormType.signIn;
});
}
}
bool validate() {
final form = formKey.currentState;
form.save();
if (form.validate()) {
form.save();
return true;
} else {
return false;
}
}
void submit() async {
if (validate()) {
try {
final auth = Provider.of(context).auth;
if (authFormType == AuthFormType.signIn) {
String uid = await auth.signinWithEmailAndPassword(_email, _password);
print("$uid");
Navigator.of(context).pushReplacementNamed('/home');
} else if (authFormType == AuthFormType.reset) {
await auth.sendPasswordResetEmail(_email);
print("password reset mail sent");
_warning = "A Password reset link has been sent to $_email";
setState(() {
authFormType = AuthFormType.signIn;
});
} else {
String uid = await auth.createUserWithEmailAndPassword(
_email, _password, _name, _regnumber, _faculty, _contact);
print("$uid");
Navigator.of(context).pushReplacementNamed('/home');
createUser();
}
} catch (e) {
print(e);
// setState(() {
_warning = e.message;
// });
}
}
}
#override
Widget build(BuildContext context) {
final _height = MediaQuery.of(context).size.height;
final _width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
title: Text('UOC Portal'),
backgroundColor: Color(0xFF4A184C),
),
body: new GestureDetector(
onTap: () {
// call this method here to hide soft keyboard
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Container(
color: Colors.white,
height: _height,
width: _width,
child: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
showAlert(),
SizedBox(
height: _height * 0.05,
),
buildHeaderText(),
buildSubHeadText(),
SizedBox(
height: _height * 0.02,
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Form(
key: formKey,
child: Column(
children: buildInputs() + buildButtons())),
)
],
),
),
),
)));
}
Widget showAlert() {
if (_warning != null) {
return Container(
color: Colors.amber,
width: double.infinity,
padding: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.error_outline),
),
Expanded(
child: AutoSizeText(
_warning,
maxLines: 3,
)),
IconButton(
icon: Icon(Icons.close),
onPressed: () {
setState(() {
_warning = null;
});
})
],
),
);
}
return SizedBox(
height: 0,
);
}
AutoSizeText buildHeaderText() {
String _headerText;
if (authFormType == AuthFormType.signIn) {
_headerText = "Welcome !!";
} else if (authFormType == AuthFormType.reset) {
_headerText = "Reset Password";
} else {
_headerText = "Sign Up";
}
return AutoSizeText(
_headerText,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 35, color: Color(0xFF4A184C), fontWeight: FontWeight.bold),
);
}
AutoSizeText buildSubHeadText() {
String _headerText;
if (authFormType == AuthFormType.signIn) {
_headerText = "Sign in to Continue";
} else if (authFormType == AuthFormType.reset) {
_headerText = "";
} else {
_headerText = "Create a new Account";
}
return AutoSizeText(
_headerText,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, color: Color(0xFF4A184C)),
);
}
List<Widget> buildInputs() {
List<Widget> textFields = [];
if (authFormType == AuthFormType.reset) {
textFields.add(
TextFormField(
keyboardType: TextInputType.text,
validator: EmailValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Email"),
onSaved: (value) => _email = value,
),
);
textFields.add(SizedBox(
height: 8,
));
return textFields;
}
//if were in the signup state add name
if (authFormType == AuthFormType.signUp) {
textFields.add(
TextFormField(
keyboardType: TextInputType.text,
validator: NameValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Name"),
onSaved: (value) => _name = value,
),
);
textFields.add(SizedBox(
height: 8,
));
textFields.add(
DropdownButtonFormField<String>(
validator:(value) {
if (value == null) {
return "Faculty can't be empty";
}
},
value: _faculty,
items: ["Science",
"Management",
"Law",
"Art",
"UCSC",
"Medicine",
"Technology",
"Nursing",
"IIM"
].map((label) => DropdownMenuItem(
child: Text(label),
value: label,
))
.toList(),
onChanged: (value) {
setState(() => _faculty = value);
},
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Faculty"),
),
);
textFields.add(SizedBox(
height: 8,
));
textFields.add(
TextFormField(
validator: RegNoValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Registration No."),
controller: reNumFieldController,
onSaved: (value) => _regnumber = value,
),
);
textFields.add(SizedBox(
height: 8,
));
textFields.add(
TextFormField(
keyboardType: TextInputType.phone,
validator: ContactValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Contact Number"),
onSaved: (value) => _contact = value,
),
);
textFields.add(SizedBox(
height: 8,
));
}
//add email and Password
textFields.add(
TextFormField(
keyboardType: TextInputType.emailAddress,
validator: EmailValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Email"),
onSaved: (value) => _email = value,
),
);
textFields.add(SizedBox(
height: 8,
));
textFields.add(
TextFormField(
validator: PasswordValidator.validate,
style: TextStyle(fontSize: 18.0, color: Color(0xFF4A184C)),
decoration: buildSignUpInputDecoration("Password"),
obscureText: true,
onSaved: (value) => _password = value,
),
);
return textFields;
}
InputDecoration buildSignUpInputDecoration(String hint) {
return InputDecoration(
//hintText: hint,
fillColor: Colors.white,
filled: true,
focusColor: Colors.amber,
labelText: hint,
errorMaxLines: 1,
hintStyle:
TextStyle(color: Color(0xFF4A184C), fontWeight: FontWeight.bold),
labelStyle:
TextStyle(color: Color(0xFF4A184C), fontWeight: FontWeight.bold),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.amber),
borderRadius: new BorderRadius.circular(25.0)),
contentPadding:
const EdgeInsets.only(left: 14.0, bottom: 10.0, top: 10.0),
);
}
List<Widget> buildButtons() {
String _switchButton, _newFormState, _submitButtonText;
bool _showForgotPasowrd = false;
if (authFormType == AuthFormType.signIn) {
_switchButton = "Don't have an account? | Sign Up";
_newFormState = "signUp";
_submitButtonText = "Sign In";
_showForgotPasowrd = true;
} else if (authFormType == AuthFormType.reset) {
_switchButton = "Return to Sign In";
_newFormState = "signIn";
_submitButtonText = "Submit";
_showForgotPasowrd = false;
} else {
_switchButton = "Have an Account? Sign In";
_newFormState = "signIn";
_submitButtonText = "Sign Up";
}
return [
SizedBox(
height: 10,
),
Container(
width: MediaQuery.of(context).size.width * 0.7,
child: RaisedButton(
onPressed: () {
submit();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
color: Color(0xFF4A184C),
textColor: Colors.amber,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
_submitButtonText,
style: TextStyle(fontSize: 20),
),
)),
),
showForgotPassowrd(_showForgotPasowrd),
FlatButton(
onPressed: () {
switchFormState(_newFormState);
},
child: Text(
_switchButton,
style: TextStyle(color: Colors.amber),
)),
];
}
Widget showForgotPassowrd(bool visibale) {
return Visibility(
child: FlatButton(
onPressed: () {
setState(() {
authFormType = AuthFormType.reset;
});
},
child: Text(
"Forgot Password?",
style: TextStyle(color: Colors.amber),
)),
visible: visibale,
);
}
}
Below one is the code for auth_service.dart file
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Stream<String> get onAuthStateChanged => _firebaseAuth.onAuthStateChanged.map(
(FirebaseUser user )=> user?.uid,
);
//Email & Password Sign Up
Future <String> createUserWithEmailAndPassword(String email, String password,
String name, String regnumber, String faculty, String contact) async {
final currentUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password,);
//update the username
var userUpdateInfo = UserUpdateInfo();
userUpdateInfo.displayName = name;
await currentUser.updateProfile(userUpdateInfo);
await currentUser.reload();
return currentUser.uid;
}
//Email & Password Sign In
Future <String> signinWithEmailAndPassword(String email, String password) async{
return (await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password)).uid;
}
//Sign Out
signOut(){
return _firebaseAuth.signOut();
}
//reset password
Future sendPasswordResetEmail(String email) async {
return _firebaseAuth.sendPasswordResetEmail(email: email);
}
}
These are the codes that I've used for creating user registration, sign-in, and reset the password. Here sign-in, sign-up and password reset appear within one page according to its state.
Please give me a better soution for this. :)
You'd need to execute createUser() before navigating to a different screen. It's best to add debugPrint() on the requests to be executed to verify that they're being called as expected.
Then update user data.
CollectionReference _userCollectionReference = FirebaseFirestore.instance
.collection('Users');
var userDocData = new Map<String, dynamic>();
userDocData['username'] = _name;
userDocData['email'] = _email;
userDocData['contact'] = _contact;
userDocData['faculty'] = _faculty;
userDocData['regnumber'] = _regnumber;
await _userCollectionReference.add(userDocData);
Also, make sure that the rules ables users to write to Firestore.
I get ERROR_INVALID_EMAIL when I try to login to firebase but if I replaced _email and _password with the real email and pass from firebase I get Log In FirebaseUser(Instance of 'PlatformUser')
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Login extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return LoginState();
}
}
class LoginState extends State<Login> {
final GlobalKey<FormState> formState = GlobalKey<FormState>();
String _email;
String _password;
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Login Page'),
centerTitle: true,
backgroundColor: Colors.deepOrange,
),
body: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Form(
key: formState,
child: Container(
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
icon: Icon(Icons.email),
hintText: 'Enter Your E-mail',
),
validator: (val) {
if (val.isEmpty) {
return 'Please Enter Your E-mail Address';
}
;
},
onSaved: (val) {
_email = val;
},
),
TextFormField(
autofocus: false,
obscureText: true,
decoration: InputDecoration(
icon: Icon(Icons.vpn_key),
hintText: 'Enter Your Password',
),
validator: (val) {
if (val.isEmpty) {
return 'Enter Your Password';
} else if (val.length < 6) {
return 'Your Password need to be at least 6 characters';
}
;
},
onSaved: (val) {
_password = val;
},
),
RaisedButton(
child: Text('Login'),
onPressed: () async {
final formdata = formState.currentState;
if (formdata.validate()) {
final FirebaseAuth _auth = FirebaseAuth.instance;
formdata.save();
AuthResult result = await _auth.signInWithEmailAndPassword(
email: _email, password: _password)
.catchError((error) => print(error.code));
if (result != null) {
FirebaseUser user = result.user;
if (user != null) {
print('Log In: $user');
}
;
}
;
}
;
},
color: Colors.deepOrange,
textColor: Colors.white,
),
],
),
),
),
],
),
),
],
),
);
}
}
i have updated My question i have provided full code why i'm getting message of invalid email should i remove strings at first or remove _email _password from string