I'm a newbie in using flutter, so this time I want to explain my problem. I created a data update form, when I want to update the data but the data cannot be updated and sent to the database, can friends here help solve my problem? Here is the source code snippet that I made. Thank you all friends. I hope that friends can also understand my question :)
edit_nasabah.dart
class EditNasabah extends StatefulWidget {
Nasabah nasabah;
EditNasabah({this.nasabah});
#override
_EditNasabahState createState() => _EditNasabahState(this.nasabah);
}
class _EditNasabahState extends State<EditNasabah> {
bool _isLoading = false;
final _formKey = GlobalKey<FormState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();
final Nasabah nasabah;
_EditNasabahState(this.nasabah);
bool _secureText = true;
String nama_debitur, alamat, no_telp, no_ktp, no_selular;
showHide() {
setState(() {
_secureText = !_secureText;
});
}
_showMsg(msg) {
final snackBar = SnackBar(
content: Text(msg),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Edit Data"),
),
body: Padding(
padding: EdgeInsets.all(10),
child: ListView(
children: [
SizedBox(
height: 10,
),
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.info, size: 50),
title: Text('Edit Form Debitur'),
subtitle: Text('Silahkan edit sesuai form dibawah ini'),
),
],
),
),
SizedBox(
height: 10,
),
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nama Debitur',
),
validator: (nameValue) {
if (nameValue.isEmpty) {
return 'Please enter your full name';
}
nasabah.nama_debitur = nameValue;
return null;
},
initialValue: "${nasabah.nama_debitur}",
),
SizedBox(
height: 10,
),
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Alamat',
),
validator: (alamatValue) {
if (alamatValue.isEmpty) {
return 'Please enter your full name';
}
alamat = alamatValue;
return null;
},
initialValue: "${nasabah.alamat}",
),
SizedBox(
height: 10,
),
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nomor Telepon',
),
validator: (notlpValue) {
if (notlpValue.isEmpty) {
return 'Please enter your full name';
}
no_telp = notlpValue;
return null;
},
initialValue: "${nasabah.no_telp}",
),
SizedBox(
height: 10,
),
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'NIK',
),
validator: (noktpValue) {
if (noktpValue.isEmpty) {
return 'Please enter your full name';
}
no_ktp = noktpValue;
return null;
},
initialValue: "${nasabah.no_ktp}",
),
SizedBox(
height: 10,
),
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'No Selular',
),
validator: (nosllValue) {
if (nosllValue.isEmpty) {
return 'Please enter your full name';
}
no_selular = nosllValue;
return null;
},
initialValue: "${nasabah.no_selular}",
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.centerRight,
margin: EdgeInsets.all(10),
child: RaisedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
_update();
}
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(80.0)),
padding: EdgeInsets.all(0.0),
child: Ink(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xff374ABE), Color(0xff64B6FF)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.circular(30.0)),
child: Container(
constraints:
BoxConstraints(maxWidth: 100.0, minHeight: 50.0),
alignment: Alignment.center,
child: Text(
_isLoading? 'Proccessing..' : 'Simpan',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 15),
),
),
),
),
),
],
),
),
],
),
));
}
This is a function to send data to the database
void _update() async {
setState(() {
_isLoading = true;
});
var data = {nasabah.nama_debitur,nasabah.alamat,nasabah.no_telp,nasabah.no_ktp,nasabah.no_selular};
print(data);
var res = await Network().updateData(data, 'mstdebitur');
var body = json.decode(res.body);
if (res.statusCode == 200) {
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('mstdebitur', json.encode(body['mstdebitur']));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Berhasil Disimpan'),
duration: Duration(seconds: 2),
));
} else {
if (body['message']['nama_debitur'] != null) {
_showMsg(body['message']['nama_debitur'][0].toString());
} else if (body['message']['alamat'] != null) {
_showMsg(body['message']['alamat'][0].toString());
} else if (body['message']['no_telp'] != null) {
_showMsg(body['message']['no_telp'][0].toString());
}
else if (body['message']['no_ktp'] != null) {
_showMsg(body['message']['no_ktp'][0].toString());
}
else if (body['message']['no_selular'] != null) {
_showMsg(body['message']['no_selular'][0].toString());
}
ScaffoldMessenger.of(context)
.showSnackBar(new SnackBar(content: Text("Gagal")));
}
setState(() {
_isLoading = false;
});
}
}
api.dart
updateData(apiURL, id) async {
var fullUrl = _url + apiURL + '/' + id.toString();
await _getToken();
return await http.put(
fullUrl,
headers: _setHeaders(),
);
}
nasabah_service.dart
static Future<List<Nasabah>> updateUser(id) async {
final response = await Network().updateData(baseUrl, id,);
List<Nasabah> list = parseResponse(response.body);
return list;
}
I hope friends can help me.
use TextEditingController for each TextFormField1
create text controller variable:
final TextEditingController _nama_debiturController = TextEditingController();
final TextEditingController _alamatController = TextEditingController();
final TextEditingController _no_telpController = TextEditingController();
final TextEditingController _no_ktpController = TextEditingController();
final TextEditingController _no_selularController = TextEditingController();
you can init value form textController in initState()
#override
void initState() {
super.initState();
_nama_debiturController.text = "hel;lo";
_alamatController.text = "Hi";
_no_telpController.text = "He";
}
And edit your TextFormField widget code:
remove initialValue: ,
add controller: ,
Example:
TextFormField(
keyboardType: TextInputType.text,
controller: _nama_debiturController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nama Debitur',
),
validator: (nameValue) {
if (nameValue!.isEmpty) {
return 'Please enter your full name';
}
nasabah.nama_debitur = nameValue;
return null;
},
),
in your _update()
void _update() async {
var data = {
_nama_debiturController.text,
_alamatController.text,
_no_telpController.text,
_no_ktpController.text,
_no_selularController.text
};
print(data);
}
your Form:
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
keyboardType: TextInputType.text,
controller: _nama_debiturController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nama Debitur',
),
validator: (nameValue) {
if (nameValue!.isEmpty) {
return 'Please enter your full name';
}
nasabah.nama_debitur = nameValue;
return null;
},
),
TextFormField(
keyboardType: TextInputType.text,
controller: _alamatController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Alamat',
),
validator: (alamatValue) {
if (alamatValue!.isEmpty) {
return 'Please enter your full name';
}
alamat = alamatValue;
return null;
},
),
TextFormField(
keyboardType: TextInputType.text,
controller: _no_telpController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nomor Telepon',
),
validator: (notlpValue) {
if (notlpValue!.isEmpty) {
return 'Please enter your full name';
}
no_telp = notlpValue;
return null;
},
),
TextFormField(
keyboardType: TextInputType.text,
controller: _no_ktpController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'NIK',
),
validator: (noktpValue) {
if (noktpValue!.isEmpty) {
return 'Please enter your full name';
}
no_ktp = noktpValue;
return null;
},
),
TextFormField(
keyboardType: TextInputType.text,
controller: _no_selularController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'No Selular',
),
validator: (nosllValue) {
if (nosllValue!.isEmpty) {
return 'Please enter your full name';
}
no_selular = nosllValue;
return null;
},
),
Container(
alignment: Alignment.centerRight,
margin: EdgeInsets.all(10),
child: RaisedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_update();
}
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(80.0)),
padding: EdgeInsets.all(0.0),
child: Ink(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xff374ABE), Color(0xff64B6FF)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.circular(30.0)),
child: Container(
constraints:
BoxConstraints(maxWidth: 100.0, minHeight: 50.0),
alignment: Alignment.center,
child: Text(
_isLoading? 'Proccessing..' : 'Simpan',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 15),
),
),
),
),
),
],
),
),
You are missing body of data in put method
updateData(apiURL, id, Map<String, String> data ) async {
var fullUrl = _url + apiURL + '/' + id.toString();
await _getToken();
return await http.put(
fullUrl,
headers: _setHeaders(),
body: jsonEncode(data),
);
}
your data
Map<String, String> data = {
"body1" : _nama_debiturController.text,
"body1": _alamatController.text,
"body1": _no_telpController.text,
"body1" : _no_ktpController.text,
"body1" : _no_selularController.text
};
print(data);
var res = await Network().updateData(data, 'mstdebitur', data);
Related
I am performing a post request after filling out a form. Any time I send the request (i.e. click on the send button), the error message in the else {} condition is what printed out but when I check the backend, the data/response has been sent/received alright.
I really cannot figure out what exactly is the cause here.
This is the entire post request code
class BorrowBook extends StatelessWidget {
BorrowBook({Key? key}) : super(key: key);
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TextEditingController _titleController = TextEditingController();
TextEditingController _authorController = TextEditingController();
TextEditingController _indexController = TextEditingController();
TextEditingController _dateController = TextEditingController();
TextEditingController _returnController = TextEditingController();
TextEditingController _nameController = TextEditingController();
PostController _postController = Get.put(PostController());
void _clearForm() {
_titleController.clear();
_authorController.clear();
_indexController.clear();
_dateController.clear();
_returnController.clear();
_nameController.clear();
}
// This is the postRequest method
postRequest(userData, url) async {
var response = await _client.post(
Uri.parse(ProjectApis.requestUrl),
body: json.encode(userData),
headers: _projectApis.headers,
);
return response;
}
// This is the sendUserRequest method
sendUserRequest() async {
var userData = {
'title': _titleController.text,
'author': _authorController.text,
'index': _indexController.text,
'borrow_date': _dateController.text,
'return_date': _returnController.text,
'borrowed_by': _nameController.text,
};
var response =
await _postController.postRequest(userData, ProjectApis.requestUrl);
var body = json.decode(response.body);
if (body['status'] == 'success') {
_clearForm();
Get.snackbar(
'Success',
'Your request has been sent successfully',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
margin: EdgeInsets.all(10),
borderColor: Colors.green,
borderWidth: 2,
colorText: Colors.white,
snackStyle: SnackStyle.FLOATING,
duration: Duration(seconds: 2),
);
} else {
Get.snackbar(
'Error',
'Something went wrong',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
margin: EdgeInsets.all(10),
borderColor: Colors.red,
borderWidth: 2,
colorText: Colors.white,
snackStyle: SnackStyle.FLOATING,
duration: Duration(seconds: 2),
);
}
}
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Padding(
padding: ProjectStyle.padding(context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TopSection(
width: width,
backIcon: Icons.chevron_left_sharp,
onPressed: () {},
text: "Borrow A Book",
height: height,
closeIcon: Icons.cancel_outlined,
),
SizedBox(height: height * 0.02),
Container(
height: height * 0.2,
width: width,
decoration: BoxDecoration(
color: ProjectColors.grey,
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
filterQuality: FilterQuality.high,
image: NetworkImage(
"https://images.unsplash.com/photo-1456513080510-7bf3a84b82f8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fGJvb2tzfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60",
),
fit: BoxFit.cover,
),
),
),
SizedBox(height: height * 0.02),
Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Book Title",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _titleController,
hintText: "Enter Book Title",
inputType: TextInputType.text,
validate: (value) {
if (value.isEmpty) {
return "Please enter a title";
}
return null;
},
saved: (value) {
_titleController.text = value;
},
),
SizedBox(height: height * 0.02),
Text(
"Author Name",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _authorController,
hintText: "Enter Author Name",
inputType: TextInputType.text,
validate: (value) {
if (value.isEmpty) {
return 'Please enter Author Name';
}
return null;
},
saved: (value) {
_authorController.text = value;
},
),
SizedBox(height: height * 0.02),
Text(
"Student Index",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _indexController,
hintText: "Enter Your Index",
inputType: TextInputType.text,
validate: (value) {
if (value.isEmpty) {
return 'Please enter your index';
}
return null;
},
saved: (value) {
_indexController.text = value;
},
),
SizedBox(height: height * 0.02),
Text(
"Borrow Date",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _dateController,
hintText: "Enter Borrow Date",
inputType: TextInputType.datetime,
validate: (value) {
if (value.isEmpty) {
return 'Please enter Borrow Date';
}
return null;
},
saved: (value) {
_dateController.text = value;
},
),
SizedBox(height: height * 0.02),
Text(
"Return Date",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _returnController,
hintText: "Enter Return Date",
inputType: TextInputType.datetime,
validate: (value) {
if (value.isEmpty) {
return 'Please enter return date';
}
return null;
},
saved: (value) {
_returnController.text = value;
},
),
SizedBox(height: height * 0.02),
Text(
"Borrowed By",
style: ProjectStyle.textStyle(context),
),
SizedBox(height: height * 0.02),
PostFormInputField(
inputController: _nameController,
hintText: "Enter Your Full Name",
inputType: TextInputType.text,
validate: (value) {
if (value.isEmpty) {
return 'Please enter your name';
}
return null;
},
saved: (value) {
_nameController.text = value;
},
),
SizedBox(height: height * 0.02),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: ProjectColors.primary,
minimumSize: Size(width * 0.95, height * 0.08),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
sendUserRequest();
}
},
child: Text("Submit Request"),
),
SizedBox(height: height * 0.02),
],
),
),
],
),
),
),
),
);
}
}
**This is the widget for the input field **
class PostFormInputField extends StatelessWidget {
const PostFormInputField({
Key? key,
required this.inputController,
required this.inputType,
required this.hintText,
required this.validate,
required this.saved,
}) : super(key: key);
final TextEditingController inputController;
final TextInputType inputType;
final String hintText;
final Function validate, saved;
#override
Widget build(BuildContext context) {
return TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction,
controller: inputController,
keyboardType: inputType,
validator: (value) {
return validate(value);
},
onSaved: (value) {
return saved(value);
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: ProjectColors.grey,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: ProjectColors.grey,
),
),
hintText: hintText,
),
);
}
}
I have not consulted any link yet as I have not seen any post with a similar question on this platform yet.
Once again, the main issue is THE MESSAGE IN THE ELSE {} CONDITION IS WHAT KEEPS BEING PRINTED OUT
I am creating a form for new product...it working well but after save button when I moved to back screen which showing all products...
There is no error but in console it is showing A FocusNode was used after being disposed
this error appears in console when I move to back with appbar's back arrow
here is my code
class EditProductScreen extends StatefulWidget {
static const routeName = 'editproductscreen';
#override
State<EditProductScreen> createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
final _pricefocusnode = FocusNode();
final _titlefocusnode = FocusNode();
final _descriptionfocusnode = FocusNode();
final _imageurlcontroller = TextEditingController();
final _imageurlfocusnode = FocusNode();
var _tempproduct =
Product(description: '', title: '', id: '', price: 0, imageUrl: '');
final _form = GlobalKey<FormState>();
#override
void dispose() {
_pricefocusnode.dispose();
_titlefocusnode.dispose();
_descriptionfocusnode.dispose();
_imageurlcontroller.dispose();
_imageurlfocusnode.dispose();
_imageurlfocusnode.removeListener(_updateimage);
super.dispose();
}
#override
void initState() {
_imageurlfocusnode.addListener(_updateimage);
super.initState();
}
void _updateimage() {
if (!_imageurlfocusnode.hasFocus) {
setState(() {});
}
}
void _saverecord() {
final result = _form.currentState?.validate();
if (!result!) return;
_form.currentState?.save();
Provider.of<ProductsProvider>(context, listen: false)
.addproduct(_tempproduct);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Product Screen'),
actions: [IconButton(onPressed: _saverecord, icon: Icon(Icons.save))],
),
body: Form(
key: _form,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: ListView(
children: [
Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: _imageurlcontroller.text.isEmpty
? Center(
child: Text(
'Enter url',
style: TextStyle(color: Colors.white, fontSize: 15),
))
: Center(
child: Text('Done',
style:
TextStyle(color: Colors.white, fontSize: 15))),
),
SizedBox(
height: 8,
),
TextFormField(
decoration: InputDecoration(
errorStyle: TextStyle(color: Colors.red, fontSize: 12),
label: Text('Title'),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
focusNode: _titlefocusnode,
textInputAction: TextInputAction.next,
onFieldSubmitted: (value) {
FocusScope.of(context).requestFocus(_pricefocusnode);
},
onSaved: (value) {
_tempproduct = Product(
description: _tempproduct.description,
title: value.toString(),
price: _tempproduct.price,
imageUrl: _tempproduct.imageUrl,
id: '',
);
},
validator: (value) {
if (value!.isEmpty) return 'Cant allow Empty title';
return null;
},
),
SizedBox(
height: 8,
),
TextFormField(
decoration: InputDecoration(
label: Text('Price'),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
focusNode: _pricefocusnode,
onFieldSubmitted: (value) {
FocusScope.of(context).requestFocus(_descriptionfocusnode);
},
onSaved: (value) {
_tempproduct = Product(
description: _tempproduct.description,
title: _tempproduct.title,
price: double.parse(value.toString()),
imageUrl: _tempproduct.imageUrl,
id: '',
);
},
validator: (value) {
if (value!.isEmpty) return 'Enter Number';
if (double.tryParse(value.toString()) == null)
return 'Enter proper double number';
if (double.parse(value.toString()) < 0)
return 'Enter greater than 0';
},
),
SizedBox(
height: 8,
),
TextFormField(
decoration: InputDecoration(
label: Text('Description'),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
focusNode: _descriptionfocusnode,
maxLines: 3,
keyboardType: TextInputType.multiline,
onSaved: (value) {
_tempproduct = Product(
description: value.toString(),
title: _tempproduct.title,
price: _tempproduct.price,
imageUrl: _tempproduct.imageUrl,
id: '',
);
},
),
SizedBox(
height: 8,
),
TextFormField(
decoration: InputDecoration(
label: Text('ImageUrl'),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
keyboardType: TextInputType.url,
textInputAction: TextInputAction.done,
controller: _imageurlcontroller,
focusNode: _imageurlfocusnode,
onFieldSubmitted: (value) {
_saverecord();
},
//todo CONFUSION HERE ON ALL ONSAVED METHOD CREATING OBJECT
onSaved: (value) {
_tempproduct = Product(
description: _tempproduct.description,
title: _tempproduct.title,
price: _tempproduct.price,
imageUrl: value.toString(),
id: '',
);
},
validator: (value) {
if (value!.isEmpty) return 'Enter url';
if (!value.startsWith('http')) return 'not a proper url';
return null;
},
),
],
),
),
),
);
},
}
and one more thing...
TextFormField's onSaved has very similar code..is there any other way to make it shorter.. I have to put in all textformfield with little change
In this method you are calling it to set state if the focus node does not have a focus by adding an ! in the condition check
void _updateimage() {
if (!_imageurlfocusnode.hasFocus) {
setState(() {});
}
}
remove the ! from the if condition. It should look like
void _updateimage() {
if (_imageurlfocusnode.hasFocus) {
setState(() {});
}
}
I faced this error when I tried to insert image
"The following NoSuchMethodError was thrown while handling a gesture:
The method 'then' was called on null.
Receiver: null
Tried calling: then(Closure: (dynamic) => Null)"
Below is my code. Hope someone can help me with it. I have no idea how to solve it. Thank you.
// ignore_for_file: import_of_legacy_library_into_null_safe, unrelated_type_equality_checks
import 'dart:io';
import 'package:dparking/model/user_model.dart';
import 'package:dparking/screens/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
class RegistrationScreen extends StatefulWidget {
const RegistrationScreen({Key? key}) : super(key: key);
#override
State<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
final _auth = FirebaseAuth.instance;
// form key
final _formKey = GlobalKey<FormState>();
// editing Controller
final nameEditingController = TextEditingController();
final emailEditingController = TextEditingController();
final passwordEditingController = TextEditingController();
final confirmPasswordEditingController = TextEditingController();
final phoneNumberEditingController = TextEditingController();
XFile? _logo;
final ImagePicker _picker = ImagePicker();
#override
Widget build(BuildContext context) {
// Name field
final nameField = TextFormField(
autofocus: false,
controller: nameEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
RegExp regex = RegExp(r'^.{3,}$');
if(value!.isEmpty){
return ("Name cannot be Empty");
}
if(!regex.hasMatch(value))
{
return ("Enter Valid Name(Min. 3 Character");
}
return null;
},
onSaved: (value)
{
nameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.account_circle),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Email field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value)
{
if(value!.isEmpty)
{
return ("Please Enter Your Email");
}
// reg expression for email validation
if(!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]").hasMatch(value))
{
return("Please Enter a valid email");
}
return null;
},
onSaved: (value)
{
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.mail),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = RegExp(r'^.{6,}$');
if(value!.isEmpty){
return ("Password is required for login");
}
if(!regex.hasMatch(value))
{
return ("Enter Valid Password(Min. 6 Character");
}
return null;
},
onSaved: (value)
{
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.vpn_key),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Confirm Password field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value)
{
if(confirmPasswordEditingController.text.length !=
passwordEditingController.text){
return "Password Does Not Match";
}
return null;
},
onSaved: (value)
{
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.vpn_key),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Confirm Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
//signup button
final signupButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.redAccent,
child: MaterialButton(
padding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: const Text("SignUp", textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold,),
),
),
);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.red),
onPressed: (){
Navigator.of(context).pop();
},
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
width: 300,
child: Image.asset("assets/images/DParking.png",
fit: BoxFit.contain,
color: Colors.black,
),
),
nameField,
const SizedBox(height: 30),
emailField,
const SizedBox(height: 30),
passwordField,
const SizedBox(height: 30),
confirmPasswordField,
const SizedBox(height: 30),
InkWell(
onTap: (){
_pickImage().then((value){ //i think the error is here
setState((){
_logo = value;
});
});
},
child: Card(
elevation: 4,
child: _logo==null ? const SizedBox(
height: 100,
width: 250,
child: Center(
child: Text('Insert Identification Card'),
),
):SizedBox(
height: 100,
width: 250,
child: Image.file(File(_logo!.path),)
),
),
),
const SizedBox(height: 30),
signupButton,
const SizedBox(height: 30),
],
),
),
),
),
),
)
);
}
void signUp(String email, String password) async
{
if (_formKey.currentState!.validate()) {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: e!.message);
});
}
}
postDetailsToFirestore() async {
// call firestore
//call user model
//send value
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
userModel.email = user!.email;
userModel.uid = user.uid;
userModel.name = nameEditingController.text;
await firebaseFirestore
.collection("users")
.doc(user.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: "Account created successfully");
Navigator.pushAndRemoveUntil(
(context),
MaterialPageRoute(builder: (context) => const HomeScreen()),
(route) => false);
}
}
_pickImage() {
}
Im trying to add a new sign in role for Rider to sign in to see the orders from customers in the same app but im not sure if im able to add it into my existing code for currently just user to register, sign in and sign up for a new role which is the rider. Would appreciate some advice or suggestion. thank you.
my user model:
class UserModel {
String? uid;
String? email;
String? firstName;
String? secondName;
UserModel({this.uid, this.email, this.firstName, this.secondName});
// receiving data from server
factory UserModel.fromMap(map) {
return UserModel(
uid: map['uid'],
email: map['email'],
firstName: map['firstName'],
secondName: map['secondName'],
);
}
// sending data to our server
Map<String, dynamic> toMap() {
return {
'uid': uid,
'email': email,
'firstName': firstName,
'secondName': secondName,
};
}
}
my sign up:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
//import 'package:grocery_shopping/pages/home/homepage.dart';
import 'package:grocery_shopping/signin.dart';
import 'package:grocery_shopping/user_model.dart';
class SignUp extends StatefulWidget {
const SignUp({Key? key}) : super(key: key);
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
final _auth = FirebaseAuth.instance;
// string for displaying the error Message
String? errorMessage;
// our form key
final _formKey = GlobalKey<FormState>();
// editing Controller
final firstNameEditingController = new TextEditingController();
final secondNameEditingController = new TextEditingController();
final emailEditingController = new TextEditingController();
final passwordEditingController = new TextEditingController();
final confirmPasswordEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
//first name field
final firstNameField = TextFormField(
autofocus: false,
controller: firstNameEditingController,
keyboardType: TextInputType.name,
validator: (value) {
RegExp regex = new RegExp(r'^.{3,}$');
if (value!.isEmpty) {
return ("First Name cannot be Empty");
}
if (!regex.hasMatch(value)) {
return ("Enter Valid name(Min. 3 Character)");
}
return null;
},
onSaved: (value) {
firstNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.account_circle),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "First Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//second name field
final secondNameField = TextFormField(
autofocus: false,
controller: secondNameEditingController,
keyboardType: TextInputType.name,
validator: (value) {
if (value!.isEmpty) {
return ("Second Name cannot be Empty");
}
return null;
},
onSaved: (value) {
secondNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.account_circle),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Second Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//email field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ("Please Enter Your Email");
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]")
.hasMatch(value)) {
return ("Please Enter a valid email");
}
return null;
},
onSaved: (value) {
firstNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.mail),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = new RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ("Password is required for login");
}
if (!regex.hasMatch(value)) {
return ("Enter Valid Password(Min. 6 Character)");
}
},
onSaved: (value) {
firstNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.vpn_key),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//confirm password field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value) {
if (confirmPasswordEditingController.text !=
passwordEditingController.text) {
return "Password don't match";
}
return null;
},
onSaved: (value) {
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: Icon(Icons.vpn_key),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Confirm Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//signup button
final signUpButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.lightBlueAccent,
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery
.of(context)
.size
.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: Text(
"SignUp",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold),
)),
);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.blue),
onPressed: () {
// passing this to our root
Navigator.of(context).pop();
},
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 180,
child: Image.asset(
"assets/grocery shopping logo.png",
fit: BoxFit.contain,
)),
SizedBox(height: 45),
firstNameField,
SizedBox(height: 20),
secondNameField,
SizedBox(height: 20),
emailField,
SizedBox(height: 20),
passwordField,
SizedBox(height: 20),
confirmPasswordField,
SizedBox(height: 20),
signUpButton,
SizedBox(height: 15),
],
),
),
),
),
),
),
);
}
void signUp(String email, String password) async {
if (_formKey.currentState!.validate()) {
try {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: "SignUp Successful");
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => SignIn()));
});
} on FirebaseAuthException catch (error) {
switch (error.code) {
case "invalid-email":
errorMessage = "Your email address appears to be malformed.";
break;
case "wrong-password":
errorMessage = "Your password is wrong.";
break;
case "user-not-found":
errorMessage = "User with this email doesn't exist.";
break;
case "user-disabled":
errorMessage = "User with this email has been disabled.";
break;
case "too-many-requests":
errorMessage = "Too many requests";
break;
case "operation-not-allowed":
errorMessage = "Signing in with Email and Password is not enabled.";
break;
default:
errorMessage = "An undefined Error happened.";
}
Fluttertoast.showToast(msg: errorMessage!);
print(error.code);
}
}
}
postDetailsToFirestore() async {
// calling our firestore
// calling our user model
// sedning these values
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
// writing all the values
userModel.email = user!.email;
userModel.uid = user.uid;
userModel.firstName = firstNameEditingController.text;
userModel.secondName = secondNameEditingController.text;
await firebaseFirestore
.collection("users")
.doc(user.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: "Account created successfully :) ");
Navigator.pushAndRemoveUntil(
(context),
MaterialPageRoute(builder: (context) => SignIn()),
(route) => false);
}
}
my sign in:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:grocery_shopping/signup.dart';
import 'package:grocery_shopping/pages/home/homepage.dart';
class SignIn extends StatefulWidget {
const SignIn({Key? key}) : super(key: key);
#override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
// form key
final _formKey = GlobalKey<FormState>();
// editing controller
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
// firebase
final _auth = FirebaseAuth.instance;
// string for displaying the error Message
String? errorMessage;
#override
Widget build(BuildContext context) {
//email field
final emailField = TextFormField(
autofocus: false,
controller: emailController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ("Please Enter Your Email");
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]")
.hasMatch(value)) {
return ("Please Enter a valid email");
}
return null;
},
onSaved: (value) {
emailController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.mail),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
//password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordController,
obscureText: true,
validator: (value) {
RegExp regex = RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ("Password is required for login");
}
if (!regex.hasMatch(value)) {
return ("Enter Valid Password(Min. 6 Character)");
}
},
onSaved: (value) {
passwordController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.vpn_key),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
));
final loginButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.lightBlueAccent,
child: MaterialButton(
padding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signIn(emailController.text, passwordController.text);
},
child: const Text(
"Sign In",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold),
)),
);
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
child: Image.asset(
"assets/grocery shopping logo.png",
fit: BoxFit.contain,
)),
const SizedBox(height: 45),
emailField,
const SizedBox(height: 25),
passwordField,
const SizedBox(height: 35),
loginButton,
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text("Don't have an account? "),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const SignUp()));
},
child: const Text(
"SignUp",
style: TextStyle(
color: Colors.blueAccent,
fontWeight: FontWeight.bold,
fontSize: 15),
),
)
])
],
),
),
),
),
),
),
);
}
// login function
void signIn(String email, String password) async {
if (_formKey.currentState!.validate()) {
try {
await _auth
.signInWithEmailAndPassword(email: email, password: password)
.then((uid) => {
Fluttertoast.showToast(msg: "Login Successful"),
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => const CatalogScreen())),
});
} on FirebaseAuthException catch (error) {
switch (error.code) {
case "invalid-email":
errorMessage = "Your email address appears to be malformed.";
break;
case "wrong-password":
errorMessage = "Your password is wrong.";
break;
case "user-not-found":
errorMessage = "User with this email doesn't exist.";
break;
case "user-disabled":
errorMessage = "User with this email has been disabled.";
break;
case "too-many-requests":
errorMessage = "Too many requests";
break;
case "operation-not-allowed":
errorMessage = "Signing in with Email and Password is not enabled.";
break;
default:
errorMessage = "An undefined Error happened.";
}
Fluttertoast.showToast(msg: errorMessage!);
print(error.code);
}
}
}
}
I have a form in flutter and when you press the button it will call a post function that register a user but i can't acces to the variables in the form.
I want to acces to the username, email and password input values to make a post and register a user
I have divide it in diferents widgets, here the code:
The form
This is the form widget that I have in my register screen
Form(
key: _formKey,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 60.0,
),
child: Column(
children: <Widget>[
new Container(
child: Image.asset(
'../../assets/logo-feec.png',
width: 200,
),
padding: EdgeInsets.symmetric(vertical: 15),
alignment: Alignment.topCenter,
),
buildUsernameTF(),
SizedBox(
height: 30.0,
),
buildEmailTF(),
SizedBox(
height: 30.0,
),
buildPasswordTF(),
SizedBox(
height: 30.0,
),
buildConfirmPasswordTF(),
Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: 200,
child: ElevatedButton.icon(
onPressed: () async {
if (_formKey.currentState.validate()) {
futureString = await resource.MyHttpService().registerUser(username, email, password);
/* Here we want to access the variables */
}
},
label: Text('Envia'),
icon: Icon(Icons.login),
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.black,
shape: const BeveledRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(3))),
)),
),
Container(
padding: EdgeInsets.all(5),
width: 200,
child: TextButton(
onPressed: () => RouterConfig.router.navigateTo(
context,
"login",
transition: TransitionType.nativeModal,
),
child: Text("Inicia sessió"),
),
)
],
)),
)
The widgets
These are the widgets called in the form
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
final TextEditingController _confirmPass = TextEditingController();
final TextEditingController _pass = TextEditingController();
Widget buildPasswordTF() {
return Container(
width: 600,
child: TextFormField(
controller: _pass,
obscureText: true,
decoration: const InputDecoration(
icon: Icon(Icons.lock),
hintText: 'Enter password',
labelText: 'Password *'),
validator: (password) {
if (password == null || password.isEmpty) {
return 'invalid Password';
}
return null;
},
),
);
}
Widget buildConfirmPasswordTF() {
return Container(
width: 600,
child: TextFormField(
controller: _confirmPass,
obscureText: true,
decoration: const InputDecoration(
icon: Icon(Icons.lock),
hintText: 'Enter password',
labelText: 'Password *'),
validator: (password) {
if (password == null || password.isEmpty) {
return 'Invalid Password';
}
if (password != _pass.text) {
return 'Passwords don\'t match';
}
return null;
},
),
);
}
Widget buildUsernameTF() {
return Container(
width: 600,
child: TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'Enter Username',
labelText: 'Username'),
validator: (username) {
if (username == null || username.isEmpty) {
return 'Invalid Username';
}
return null;
},
),
);
}
Widget buildEmailTF() {
return Container(
width: 600,
child: TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.mail),
hintText: 'Enter email',
labelText: 'Email *'),
validator: (email) {
if (EmailValidator.validate(email) != true) {
return 'Invalid Email';
}
if (email == null || email.isEmpty) {
return 'Invalid Email';
}
return null;
},
),
);
}
The answer to this will depend on your widget tree but ideally, you would be able to access the TextEditingControllers inside your TextFormFields.
You will need to create TextEditingControllers for each TextFormField:
TextEditingController emailController = TextEditingController();
And then when you submit, you need to access the controller and get the text.
onPressed: () async {
if (_formKey.currentState.validate()) {
futureString = await resource.MyHttpService().registerUser(username, email, password);
/* Here we want to access the variables */
print('Email text: ' + emailController.text);
}
},