Manually entered data not being saved in Firebase document - firebase

I have a screen with several text fields and some are populated when it is created. This is done in the initState() function. When I enter data into the empty text fields and then save the data to a firebase document only the data that is manually entered after the screen has been created is saved to the document. Below is the code for the screen. Please help with this.
final _firebaseAuthUser = FirebaseAuth.instance.currentUser;
final agentsRef = FirebaseFirestore.instance.collection(('agents'));
final agencyRef = FirebaseFirestore.instance.collection(('agency'));
class AgentProfileScreen extends StatefulWidget {
static const String id = 'agent_profile_screen';
final Agents agents;
AgentProfileScreen([this.agents]);
#override
_AgentProfileScreenState createState() => _AgentProfileScreenState();
}
class _AgentProfileScreenState extends State<AgentProfileScreen> {
//final _auth = FirebaseAuth.instance;
final _db = FirebaseFirestore.instance;
final emailController = TextEditingController();
final passwordController = TextEditingController();
final fNameController = TextEditingController();
final lNameController = TextEditingController();
final address1Controller = TextEditingController();
final address2Controller = TextEditingController();
final cityController = TextEditingController();
final stateController = TextEditingController();
final zipController = TextEditingController();
final cellPhoneController = TextEditingController();
final officePhoneController = TextEditingController();
final agencyController = TextEditingController();
#override
void dispose() {
emailController.dispose();
passwordController.dispose();
fNameController.dispose();
lNameController.dispose();
address1Controller.dispose();
address2Controller.dispose();
cityController.dispose();
stateController.dispose();
zipController.dispose();
cellPhoneController.dispose();
officePhoneController.dispose();
agencyController.dispose();
super.dispose();
}
bool showSpinner = false;
String email;
String password;
String fName;
String lName;
String address1;
String address2;
String city;
String state;
String zip;
String cellPhone;
String officePhone;
String agency;
String _currentAgentState;
String _currentAgency;
getCurrentAgentProfile() async {
final DocumentSnapshot currentAgentProfile =
await agentsRef.doc(globals.currentUid).get();
//String currentAgencyId = currentAgentProfile.data()["agencyId"];
final DocumentSnapshot currentAgencyProfile =
await agencyRef.doc(globals.agencyId).get();
if (globals.newAgent == true) {
emailController.text = "";
fNameController.text = "";
lNameController.text = "";
address1Controller.text = currentAgencyProfile.data()['address1'];
address2Controller.text = currentAgencyProfile.data()['address2'];
cityController.text = currentAgencyProfile.data()['city'];
stateController.text = currentAgencyProfile.data()['state'];
globals.currentAgencyState = currentAgencyProfile.data()['state'];
zipController.text = currentAgencyProfile.data()['zipCode'].toString();
cellPhoneController.text = currentAgencyProfile.data()['cellPhone'];
officePhoneController.text = currentAgencyProfile.data()['officePhone'];
agencyController.text = currentAgencyProfile.data()['name'];
} else {
// existing record
// Updates Controllers
emailController.text = currentAgentProfile.data()["email"];
fNameController.text = currentAgentProfile.data()['fName'];
lNameController.text = currentAgentProfile.data()['lName'];
address1Controller.text = currentAgentProfile.data()['address1'];
address2Controller.text = currentAgentProfile.data()['address2'];
cityController.text = currentAgentProfile.data()['city'];
stateController.text = currentAgentProfile.data()['state'];
zipController.text = currentAgentProfile.data()['zipCode'].toString();
cellPhoneController.text = currentAgentProfile.data()['cellPhone'];
officePhoneController.text = currentAgentProfile.data()['officePhone'];
agencyController.text = currentAgentProfile.data()['agency'];
// Updates State
new Future.delayed(Duration.zero, () {
final agentProvider =
Provider.of<AgentProvider>(context, listen: false);
agentProvider.loadValues(widget.agents);
});
}
}
List<DropdownMenuItem<String>> _dropDownState;
List<DropdownMenuItem<String>> getDropDownState() {
List<DropdownMenuItem<String>> items = [];
for (String state in globals.states) {
items.add(new DropdownMenuItem(
value: state,
child: new Text(
state,
)));
}
return items;
}
void changedDropDownState(String selected_state) {
setState(() {
_currentAgentState = selected_state;
});
globals.selectedAgentState = selected_state;
}
void changedDropDownAgency(String selected_agency) {
setState(() {
_currentAgency = selected_agency;
});
globals.selectedAgency = selected_agency;
}
#override
void initState() {
getCurrentAgentProfile();
_currentAgentState = globals.currentAgentState;
_currentAgency = globals.agencyId;
_currentAgentState = globals.currentAgencyState;
super.initState();
_dropDownState = getDropDownState();
}
#override
Widget build(BuildContext context) {
// Get the stream of agents created in main.dart
final agentProvider = Provider.of<AgentProvider>(context);
final _firestoreService = FirestoreService();
String _chosenState = 'Select State';
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/Appbar_logo.png',
fit: BoxFit.cover, height: 56),
],
),
),
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Agent Profile',
style: TextStyle(
fontSize: 30,
),
),
SizedBox(
height: 8.0,
),
// Email entry text field
TextField(
controller: fNameController,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changefName(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'First Name', labelText: 'First Name'),
),
SizedBox(
height: 8.0,
),
TextField(
controller: lNameController,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changelName(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Last Name', labelText: 'Last Name'),
),
SizedBox(
height: 8.0,
),
Container(
child: StreamBuilder(
stream: _db.collection('agency').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return new DropdownButton<String>(
hint: new Text("Select Agency"),
value: _currentAgency,
onChanged: changedDropDownAgency,
items: snapshot.data.docs
.map<DropdownMenuItem<String>>((document) {
return new DropdownMenuItem<String>(
value: document.id,
child: new Text(document.data()['name']),
);
}).toList(),
);
}
;
}),
),
SizedBox(
height: 8.0,
),
TextField(
controller: address1Controller,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changeaddress1(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Address 1', labelText: 'Address 1'),
),
SizedBox(
height: 8.0,
),
TextField(
controller: address2Controller,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changeaddress2(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Address 2', labelText: 'Address 2'),
),
SizedBox(
height: 8.0,
),
TextField(
controller: cityController,
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changecity(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'City', labelText: 'City'),
),
SizedBox(
height: 8.0,
),
DropdownButton(
value: _currentAgentState,
items: _dropDownState,
hint: Text('Choose State'),
onChanged: changedDropDownState,
),
SizedBox(
height: 8.0,
),
TextField(
controller: zipController,
keyboardType: TextInputType.phone,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changezipCode(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Zip Code', labelText: 'Zip Code'),
),
SizedBox(
height: 8.0,
),
TextField(
controller: cellPhoneController,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changecellPhone(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Cell Phone', labelText: 'Cell Phone'),
),
SizedBox(
height: 8.0,
),
TextField(
controller: officePhoneController,
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
onChanged: (value) {
agentProvider.changeofficePhone(value);
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Office Phone', labelText: 'Office Phone'),
),
SizedBox(
height: 8.0,
),
RoundedButton(
title: 'Save',
colour: Colors.blueAccent,
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
agentProvider.saveAgent();
globals.newAgent = false;
globals.currentAgentState = _currentAgentState;
await _firestoreService.saveDeviceToken();
Navigator.pushNamed(context, Home_Screen.id);
setState(() {
showSpinner = false;
});
} catch (e) {
// todo: add better error handling
print(e);
}
},
),
SizedBox(
height: 8.0,
),
(widget != null)
? RoundedButton(
title: 'Delete',
colour: Colors.red,
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
agentProvider.deleteAgent(globals.currentUid);
Navigator.pushNamed(
context, AgentDashboardScreen.id);
setState(() {
showSpinner = false;
});
} catch (e) {
// todo: add better error handling
print(e);
}
},
)
: Container()
],
),
),
),
),
);
}
}
Below is the provider code.
class AgentProvider with ChangeNotifier {
final firestoreService = FirestoreService();
final agencyRef = FirebaseFirestore.instance.collection(('agency'));
String _fName;
String _lName;
String _address1;
String _address2;
String _city;
String _state;
int _zipCode;
String _cellPhone;
String _officePhone;
String _agencyId;
String _agency;
//Getters
String get fName => _fName;
String get lName => _lName;
String get address1 => _address1;
String get address2 => _address2;
String get city => _city;
String get state => globals.selectedAgentState;
int get zipCode => _zipCode;
String get cellPhone => _cellPhone;
String get officePhone => _officePhone;
String get agencyId => globals.agencyId;
String get agency => _agency;
//Setters
changefName(String value) {
_fName = value;
notifyListeners();
}
changelName(String value) {
_lName = value;
notifyListeners();
}
changeaddress1(String value) {
_address1 = value;
notifyListeners();
}
changeaddress2(String value) {
_address2 = value;
notifyListeners();
}
changecity(String value) {
_city = value;
notifyListeners();
}
changestate(String value) {
_state = value;
notifyListeners();
}
// Convert String to int
changezipCode(String value) {
_zipCode = int.parse(value);
notifyListeners();
}
// Convert String to int
changecellPhone(String value) {
_cellPhone = value;
notifyListeners();
}
// Convert String to int
changeofficePhone(String value) {
_officePhone = value;
notifyListeners();
}
changeAgency(String value) {
_agency = value;
notifyListeners();
}
loadValues(Agents agents) {
_fName = agents.fName;
_lName = agents.lName;
_address1 = agents.address1;
_address2 = agents.address2;
_city = agents.city;
_state = globals.selectedAgentState;
_zipCode = agents.zipcode;
_cellPhone = agents.cellPhone;
_officePhone = agents.officePhone;
_agencyId = globals.agencyId;
_agency = agents.agency;
}
saveAgent() async {
final newAgent = new Map();
if (globals.newAgent == true) {
final DocumentSnapshot currentAgencyProfile =
await agencyRef.doc(globals.agencyId).get();
var newAgent = Agents(
agentId: globals.currentUid,
fName: _fName,
lName: _lName,
address1: currentAgencyProfile.data()['address1'],
address2: currentAgencyProfile.data()['address2'],
city: currentAgencyProfile.data()['city'],
state: globals.selectedAgentState,
zipcode: currentAgencyProfile.data()['zipCode'],
cellPhone: currentAgencyProfile.data()['cellPhone'],
officePhone: currentAgencyProfile.data()['officePhone'],
agencyId: globals.agencyId,
agency: agency);
firestoreService.saveAgent(newAgent);
} else {
var newAgent = Agents(
agentId: globals.currentUid,
fName: _fName,
lName: _lName,
address1: _address1,
address2: _address2,
city: _city,
state: globals.selectedAgentState,
zipcode: _zipCode,
cellPhone: _cellPhone,
officePhone: _officePhone,
agencyId: globals.agencyId,
agency: agency);
firestoreService.saveAgent(newAgent);
}
//firestoreService.saveAgent(newAgent);
_fName = "";
_lName = "";
_address1 = "";
_address2 = "";
_city = "";
_state = "";
_zipCode = null;
_cellPhone = "";
_officePhone = "";
_agencyId = "";
_agency = "";
}
Here is the saveAgent function. I really don't think this is the problem but here it is anyway.
Future<void> saveAgent(Agents agents) {
return _db.collection('agents').doc(globals.currentUid).set(agents.toMap());
}

initState is designed to be a synchronous function, and since your async function will take some time to execute, it will not work out as you expect. To call async function make use of FutureBuilder widget inside your build function.

Related

Not Finding and Deleting a Firebase Document

I am trying to make a form so that whenever you enter information and press a button, it will delete an item from the firebase database. I got the addUser code working, but when I got to the deleteUser, it compiles fine but then whenever I submit a form it doesn't show that I deleted it. I know I am putting in the same data exactly, so I think the problem is either the async in my function title or the await in my itemsSnapshot, but I have no idea since deleting a document this way is super weird. What am I doing wrong? (I am not including the imports because I'm not sure if that is sensitive data)
class AdminScreen extends StatefulWidget {
const AdminScreen({Key? key}) : super(key: key);
#override
State<AdminScreen> createState() => _AdminScreenState();
}
class _AdminScreenState extends State<AdminScreen> {
CollectionReference items = FirebaseFirestore.instance.collection('items');
reloadUser() {
setState(() {});
}
//this section is for adding stuff to database
String name = "";
String type = "";
String location="";
String imageURL = "";
String claimed = "false";
bool addDataVisible = true;
//end of this section
TextEditingController nameController = TextEditingController();
TextEditingController typeController = TextEditingController();
TextEditingController locationController = TextEditingController();
TextEditingController imageURLController = TextEditingController();
String deleteName = "";
String deleteType = "";
String deleteLocation = "";
TextEditingController deleteNameController = TextEditingController();
TextEditingController deleteTypeController = TextEditingController();
TextEditingController deleteLocationController = TextEditingController();
Object addUser() {
// Call the user's CollectionReference to add a new user
if(name!="" && type!="" && location!="") {
return items
.add({
'name': name,
'type': type,
'location': location,
'image': imageURL,
'claimed': claimed
});
// .then((value) => print("User Added"))
// .catchError((error) => print("Failed to add user: $error"));
}else{
return "There was a null error";
}
}
String idDelete = "";
Future<Object> deleteUser() async{
var itemsSnapshot = await items.get();
// Call the user's CollectionReference to add a new user
if (name != "" && type != "" && location != "") {
for (var document in itemsSnapshot.docs) {
if (document[name] == deleteName &&
document[type] == deleteType &&
document[location] == deleteLocation) {
idDelete = document.id;
}
}
print(idDelete);
items.doc(idDelete).delete();
print("user deleted success");
return items;
} else {
return "There was a null error";
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Admin'),
),
body: SingleChildScrollView(
child: Column(children: [
FirebaseAuth.instance.currentUser == null ? LoginButton(
updateState: reloadUser,) : //Text('logged in'),
//render the new widgets
Visibility(
visible: addDataVisible,
child: Column(
children: [
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name of Item to Add',
),
controller: nameController,
onChanged: (text) {
setState(() {
name = text;
});
},
//for description
),
TextField(
controller: typeController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Type of Item to Add',
),
onChanged: (text) {
setState(() {
type = text;
});
},
//for location found
),
TextField(
controller: locationController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Location of Item to Add',
),
onChanged: (text) {
setState(() {
location = text;
});
},
//for location found
),
TextField(
controller: imageURLController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Image URL of Item (put it in the folder)',
),
onChanged: (text) {
setState(() {
imageURL = text;
});
},
//for location found
),
TextButton(
child: const Text('Click Here to Submit New Item to Database'),
onPressed: addUser,
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
overlayColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return Colors.blue.withOpacity(0.04);
}
if (states.contains(MaterialState.focused) ||
states.contains(MaterialState.pressed)) {
return Colors.blue.withOpacity(0.12);
}
return null; // Defer to the widget's default.
},
),
),
),
//THIS SECTION IS FOR DELETING ITEMS
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name of Item to Delete',
),
controller: deleteNameController,
onChanged: (text) {
setState(() {
deleteName = text;
});
},
//for description
),
TextField(
controller: deleteTypeController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Type of Item to Delete',
),
onChanged: (text) {
setState(() {
deleteType = text;
});
},
//for location found
),
TextField(
controller: deleteLocationController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Location of Item to Delete',
),
onChanged: (text) {
setState(() {
deleteLocation = text;
});
},
//for location found
),
TextButton(
child: const Text('Click Here to Delete Item to Database'),
onPressed: deleteUser,
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
overlayColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return Colors.blue.withOpacity(0.04);
}
if (states.contains(MaterialState.focused) ||
states.contains(MaterialState.pressed)) {
return Colors.blue.withOpacity(0.12);
}
return null; // Defer to the widget's default.
},
),
),
),
],
),
),
]),
),
);
}}

The non-nullable local variable 'result' must be assigned before it can be used

I cannot find the solution to this problem. I am creating a sign up screen connected to firebase but it is giving me this error, "The non-nullable local variable 'result' must be assigned before it can be used. Try giving it an initializer expression, or ensure that it's assigned on every execution path."
The error is here. On the first and third line under result.
FirebaseFirestore.instance.collection("User").doc(result.user!.uid).set({
"UserName": userName.text,
"UserId": result.user!.uid,
"UserEmail": email.text,
"UserAddress": address.text,
"UserGender": isMale == true ? "Male" : "Female",
"UserNumber": phoneNumber.text,
});
This is the whole code
`import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:e_commerce_application/screens/homepage.dart';
import 'package:e_commerce_application/screens/login.dart';
import 'package:e_commerce_application/widgets/changescreen.dart';
import 'package:e_commerce_application/widgets/mybutton.dart';
import 'package:e_commerce_application/widgets/mytextformField.dart';
import 'package:e_commerce_application/widgets/passwordtextformfield.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
String p =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(p);
bool obserText = true;
final TextEditingController email = TextEditingController();
final TextEditingController userName = TextEditingController();
final TextEditingController phoneNumber = TextEditingController();
final TextEditingController password = TextEditingController();
final TextEditingController address = TextEditingController();
bool isMale = true;
bool isLoading = false;
class _SignUpState extends State<SignUp> {
void submit() async {
UserCredential result;
try {
setState(() {
isLoading = true;
});
result = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email.text, password: password.text);
print(result);
} on PlatformException catch (error) {
var message = "Please Check Your Internet Connection ";
if (error.message != null) {
message = error.message!;
}
_scaffoldKey.currentState!.showSnackBar(SnackBar(
content: Text(message.toString()),
duration: Duration(milliseconds: 600),
backgroundColor: Theme.of(context).primaryColor,
));
setState(() {
isLoading = false;
});
} catch (error) {
setState(() {
isLoading = false;
});
_scaffoldKey.currentState!.showSnackBar(SnackBar(
content: Text(error.toString()),
duration: Duration(milliseconds: 600),
backgroundColor: Theme.of(context).primaryColor,
));
print(error);
}
FirebaseFirestore.instance.collection("User").doc(result.user!.uid).set({
"UserName": userName.text,
"UserId": result.user!.uid,
"UserEmail": email.text,
"UserAddress": address.text,
"UserGender": isMale == true ? "Male" : "Female",
"UserNumber": phoneNumber.text,
});
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (ctx) => HomePage()));
setState(() {
isLoading = false;
});
}
void vaildation() async {
if (userName.text.isEmpty &&
email.text.isEmpty &&
password.text.isEmpty &&
phoneNumber.text.isEmpty &&
address.text.isEmpty) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("All Flied Are Empty"),
),
);
} else if (userName.text.length < 6) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Name Must Be 6 "),
),
);
} else if (email.text.isEmpty) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Email Is Empty"),
),
);
} else if (!regExp.hasMatch(email.text)) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Please Try Vaild Email"),
),
);
} else if (password.text.isEmpty) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Password Is Empty"),
),
);
} else if (password.text.length < 8) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Password Is Too Short"),
),
);
} else if (phoneNumber.text.length < 11 || phoneNumber.text.length > 11) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Phone Number Must Be 11 "),
),
);
} else if (address.text.isEmpty) {
_scaffoldKey.currentState!.showSnackBar(
SnackBar(
content: Text("Address Is Empty "),
),
);
} else {
submit();
}
}
Widget _buildAllTextFormField() {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
MyTextFormField(
name: "UserName",
controller: userName,
),
SizedBox(
height: 10,
),
MyTextFormField(
name: "Email",
controller: email,
),
SizedBox(
height: 10,
),
PasswordTextFormField(
obserText: obserText,
controller: password,
name: "Password",
onTap: () {
FocusScope.of(context).unfocus();
setState(() {
obserText = !obserText;
});
},
),
SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
setState(() {
isMale = !isMale;
});
},
child: Container(
height: 60,
padding: EdgeInsets.only(left: 10),
width: double.infinity,
decoration: BoxDecoration(border: Border.all(color: Colors.grey)),
child: Center(
child: Row(
children: [
Text(
isMale == true ? "Male" : "Female",
style: TextStyle(color: Colors.black87, fontSize: 18),
),
],
),
),
),
),
SizedBox(
height: 10,
),
MyTextFormField(
name: "Phone Number",
controller: phoneNumber,
),
SizedBox(
height: 10,
),
MyTextFormField(
name: "Address",
controller: address,
),
],
),
);
}
Widget _buildBottomPart() {
return Container(
margin: EdgeInsets.symmetric(horizontal: 10),
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildAllTextFormField(),
SizedBox(
height: 10,
),
isLoading == false
? MyButton(
name: "SignUp",
onPressed: () {
vaildation();
},
)
: Center(
child: CircularProgressIndicator(),
),
ChangeScreen(
name: "Login",
whichAccount: "I Have Already An Account!",
onTap: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (ctx) => Login(),
),
);
},
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: ListView(
children: [
Container(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Register",
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
],
),
),
Container(
height: 500,
child: _buildBottomPart(),
),
],
),
);
}
}
`
You are assigning result in your try catch, and accessing it after your try catch.
So if anything happens in your try block, result will never be assigned, and you cannot access whatever you want on it.
Solution would be to put your Firestore Call in your try catch block.
try {
setState(() {
isLoading = true;
});
result = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email.text, password: password.text);
print(result);
FirebaseFirestore.instance.collection("User").doc(result.user!.uid).set({
"UserName": userName.text,
"UserId": result.user!.uid,
"UserEmail": email.text,
"UserAddress": address.text,
"UserGender": isMale == true ? "Male" : "Female",
"UserNumber": phoneNumber.text,
});
Null safety in dart also cause this error in my code. The only solution is to assign a pre-define value to variable.
String imagePath = "path";
String imageName = '/image.jpeg';
I was getting this error in last line, in var imagePath.
class _newpostState extends State<newpost> {
//class newpost extends StatefulWidget {
//const newpost({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
String imagePath = "path";
String imageName = '/image.jpeg';
void pickImage() async {
final ImagePicker _picker = ImagePicker();
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
print(image!.name);
setState(() {
imagePath = image.path;
imageName = image.name;
});
}
final TextEditingController titlecontroller = TextEditingController();
final TextEditingController DcripController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
void submit() async {
//for post database
FirebaseAuth auth = FirebaseAuth.instance;
FirebaseFirestore firestore = FirebaseFirestore.instance;
//for storage
firebase_storage.FirebaseStorage storage =
firebase_storage.FirebaseStorage.instance;
try {
File file = File(imagePath);
await storage.ref(imageName).putFile(file);
It's so, frustrating to read "variable must be assigned before it can be used" because you already assigned the variable.
to solve this issue, provide a default value when you create the variable.
suppose the variable is a string.
String result; // instead of this
String result= ""; // use this

Reading and displaying userData from Firestore - Flutter

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()),
),
],
);
}
)
]
)
);
}
}

User registration and authentication in flutter

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.

Flutter ListView is not updating when the list items are changed

I started learning Flutter. I am developing a simple application using it. Now, I am developing a feature where my application will display the records from the SQLite database and where the user adds the new records into the SQLite database. But my ListView is displaying the blank screen.
I have a class called DatabaseHelper with the following code.
class DatabaseHelper {
static DatabaseHelper _databaseHelper;
Database _database;
String noteTable = 'note_table';
String colId = 'id';
String colTitle = 'title';
String colDescription = 'description';
String colPriority = 'priority';
String colDate = 'date';
DatabaseHelper._createInstance();
factory DatabaseHelper() {
if (_databaseHelper == null) {
_databaseHelper = DatabaseHelper._createInstance();
}
return _databaseHelper;
}
Future<Database> get database async {
if (_database == null) {
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'notes.db';
var notesDatabase = await openDatabase(path, version: 1, onCreate: _createDB);
return notesDatabase;
}
void _createDB(Database db, int newVersion) async {
await db.execute('CREATE TABLE $noteTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colTitle TEXT, $colDescription TEXT, $colPriority INTEGER, $colDate TEXT)');
}
Future<List<Map<String, dynamic>>> getNoteMapList() async {
Database db = await this.database;
return await db.query(noteTable, orderBy: '$colPriority ASC');
}
Future<int> insertNote(Note note) async {
Database db = await this.database;
return await db.insert(noteTable, note.toMap());
}
Future<int> updateNote(Note note) async {
var db = await this.database;
return await db.update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
}
Future<int> deleteNote(int id) async {
var db = await this.database;
return await db.rawDelete('DELETE FROM $noteTable WHERE $colId = $id');
}
Future<int> getCount() async {
Database db = await this.database;
List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT(*) FROM $noteTable');
return Sqflite.firstIntValue(x);
}
}
Then I have a widget called NoteList with the following code where the list of items are displayed.
class NoteList extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _NoteListState();
}
}
class _NoteListState extends State<NoteList> {
List<Note> _notes = [];
int _count = 0;
DatabaseHelper _databaseHelper = DatabaseHelper();
_NoteListState() {
this._notes = getNotes();
this._count = _notes.length;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Notes"),),
body: Container(
child: getListView(context),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
navigateToNoteForm("Add Note");
},
),
);
}
Widget getListView(BuildContext context) {
return ListView.builder(
itemCount: _count,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: _notes[index].priority == 1? Colors.yellow: Colors.red,
child: Icon(_notes[index].priority == 1 ? Icons.arrow_right : Icons.add),
),
title: Text(_notes[index].title),
subtitle: Text(_notes[index].date),
trailing: Icon(Icons.delete),
onTap: () {
navigateToNoteForm("Edit Note", _notes[index]);
},
);
});
}
void navigateToNoteForm(String pageTitle, [Note note]) async {
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return NoteForm(pageTitle, note);
}));
if (result) {
setState(() {
debugPrint("Updating list");
_notes = getNotes();
_count = _notes.length;
});
}
}
List<Note> getNotes() {
List<Note> notes = List<Note>();
Future<List<Map<String, dynamic>>> notesFuture = _databaseHelper.getNoteMapList();
notesFuture.then((notesMap) {
debugPrint("Total notes found in the database ${notesMap.length}");
notesMap.forEach((map) {
notes.add(Note.fromMapObject(map));
});
});
return notes;
}
}
Then I also have another widget class called NoteForm with the following code.
class NoteForm extends StatefulWidget {
String _title = "";
Note _note = null;
NoteForm(String title, [Note note]) {
this._title = title;
this._note = note;
}
#override
State<StatefulWidget> createState() {
return _NoteFormState();
}
}
class _NoteFormState extends State<NoteForm> {
double _minimumPadding = 15.0;
var _priorities = [ 1, 2 ];
var _titleController = TextEditingController();
var _descriptionController = TextEditingController();
var _dateController = TextEditingController();
DatabaseHelper _databaseHelper = DatabaseHelper();
var _selectedPriority = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget._title),),
body: Builder(
builder: (scaffoldContext) => Form(
child: Column(
children: <Widget>[
Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding),
child: TextFormField(
controller: _titleController,
decoration: InputDecoration(
labelText: "Title",
hintText: "Enter title"
),
),
),
),
Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding),
child: TextFormField(
controller: _descriptionController,
decoration: InputDecoration(
labelText: "Description",
hintText: "Enter description"
),
),
)
),
Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding),
child: TextFormField(
controller: _dateController,
decoration: InputDecoration(
labelText: "Date",
hintText: "Enter date"
),
),
),
),
Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding),
child: DropdownButton<int>(
value: _selectedPriority,
items: _priorities.map((dropdownItem) {
return DropdownMenuItem<int>(
value: dropdownItem,
child: Text(dropdownItem == 1? "Low": "High"),
);
}).toList(),
onChanged: (int newSelectedValue) {
setState(() {
_selectedPriority = newSelectedValue;
});
},
),
),
),
Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding),
child: RaisedButton(
child: Text(
"Save"
),
onPressed: () {
_save(scaffoldContext);
},
),
),
)
],
),
),
)
);
}
void _save(BuildContext context) async {
Note note = Note();
note.title = _titleController.text;
note.description = _descriptionController.text;
note.date = _dateController.text;
note.priority = _selectedPriority;
if (widget._note != null && widget._note.id!=null) {
//update
_databaseHelper.updateNote(note);
this.showSnackBar(context, "Note has been updated.");
} else {
//create
_databaseHelper.insertNote(note);
this.showSnackBar(context, "Note has been added.");
}
closeForm(context);
}
void showSnackBar(BuildContext context, String message) {
var snackBar = SnackBar(
content: Text(message),
action: SnackBarAction(
label: "UNDO",
onPressed: () {
},
),
);
Scaffold.of(context).showSnackBar(snackBar);
}
void closeForm(BuildContext context) {
Navigator.pop(context, true);
}
}
When I run my application, it is just displaying the blank screen as follows.
As you can see I am logging out the number of records returned from the database using debugPrint method. It is saying that there are 6 records within the database. It is just not displaying the records. What is wrong with my code and how can I fix it?
As i mention in comment that was happening because of async task take some time to perform and if you do not keep it async then setState function execute before actual data load or set.
So Following changes solve your issue.
make getNotes async method And
getNotes().then((noteresponce){ setState((){ _notes=noteresponce; _count = _notes.length;} });

Resources