TextFormField Validation Not Working Correctly - flutter

I am new to Flutter development, and I'm currently working on the sign in screen for my first full application. I apologize if this has already been asked, but I cannot figure out where my code is going wrong. I'm attempting to test basic form validation, just checking whether anything has been written into the form fields before I continue.
The code for my form is as follows:
class SignInForm extends StatefulWidget {
const SignInForm({super.key});
#override
SignInFormState createState() {
return SignInFormState();
}
}
class SignInFormState extends State<SignInForm> {
final _signInFormKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Username',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter a valid username';
}
return null;
},
),
Padding(
padding: EdgeInsets.only(top: 20),
child: TextFormField(
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Password',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter a valid password';
}
return null;
},
),
),
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Color(0xFF0b2240)),
),
onPressed: () {
if (_signInFormKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Log In'),
),
],
),
),
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Color(0xFF0b2240)),
),
onPressed: () {
if (_signInFormKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('+ Sign Up'),
),
],
),
),
],
),
);
}
}
Thanks in advance for any help improving my code!

Your forgot the key for the form widget, that's why validation don't work.
#override
Widget build(BuildContext context) {
return Form(
key: _signInFormKey,
child: Column(
...
More infos here : https://docs.flutter.dev/cookbook/forms/validation

Related

Flutter Simple Login Page

I am a flutter beginner. How to make a simple login page in flutter like this. I tried, but I get a lot of errors. Can anyone help to resolve this?
Please see here to find what I want
Thanks in advance!...............
My code:
Container(
width: 350,
child: TextField(
decoration: InputDecoration(
label Text: 'Email',
),
),
),
Container(
width: 350,
child: TextField(
obscureText: true,
decoration: InputDecoration(
label Text: 'Password',
suffixIcon: Icon(CupertinoIcons.eye_slash_fill,
size: 17),
),
),
),
Padding(
padding: EdgeInserts.fromLTRB(20,20,40,40),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Forget Password')
],
),
),
GestureDetector(
child: Container(
alignment: Alignment.center,
width: 250,
child: TextField(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: EdgeInsets.all(top: 12),
child: Text('LOGIN')
),
),
),
),
],
),
),
),
);
}
}
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
String _email, _password;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login Screen'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
validator: (input) {
if (input.isEmpty) {
return 'Please enter an email';
}
return null;
},
onSaved: (input) => _email = input,
decoration: InputDecoration(
labelText: 'Email',
),
),
TextFormField(
validator: (input) {
if (input.length < 6) {
return 'Your password needs to be at least 6 characters';
}
return null;
},
onSaved: (input) => _password = input,
decoration: InputDecoration(
labelText: 'Password',
),
obscureText: true,
),
RaisedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
// This is where you can handle the login logic
}
},
child: Text('Submit'),
),
],
),
),
),
);
}
}
This is sample code of Login screen.
For get more design and code head to https://flutterawesome.com/tag/login-screen
there is lot of sample code available. And I think you can get better idea from it.

I want to add EDIT and DELETE functionality on a ListTile

I want to add delete and edit functionality in my lists using PopMenuItem. As shown in the picture, when I click on menu icon on any list, two options appears, when I click on delete button, it should delete that complete list, and when I click on edit, it should let me edit those Text Fields in ListTile, so far I have attempted this code to delete list, but it isn't working. And I have no idea, how can I achieve that edit functionality in this, Someone please help me out.
Here is the picture:
Here is the code to delete list:
PopupMenuItem(
child: FlatButton(
child: Text('Delete'),
onPressed: () {
widget.models.removeAt(index);
setState(() => widget.models = widget.models);
},
),
),
And here is the complete code:
class DialogForm extends StatefulWidget {
// List<Model> models = <Model>[];
// Model tempModel = Model();
// final newModel = Model();
DialogForm();
#override
State<DialogForm> createState() => _ResultState();
List<Model> models = <Model>[];
Model tempModel = Model();
#override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Model>('model', tempModel));
}
}
class _ResultState extends State<DialogForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return (Scaffold(
appBar: AppBar(title: Text('Successful')),
body: Container(
margin: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: ListView.builder(
itemCount: widget.models.length,
itemBuilder: (BuildContext context, index) => Card(
elevation: 6,
margin: EdgeInsets.all(10),
child: PopupMenuButton<String>(
onSelected: (String value) {
setState(() {
});
},
child: ListTile(
title: Text(widget.models[index].firstName),
subtitle: Text(widget.models[index].lastName),
trailing: Icon(Icons.menu),
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
PopupMenuItem(
child: FlatButton(
child: Text('Edit'),
onPressed: () {
},
),
),
PopupMenuItem(
child: FlatButton(
child: Text('Delete'),
onPressed: () {
widget.models.removeAt(index);
setState(() => widget.models = widget.models);
},
),
),
],
),
)
)
),
Align(
child: RaisedButton(
child: Text('Click Me!'),
onPressed: (){
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
content: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
right: -40,
top: -40,
child: InkResponse(
onTap: () {
Navigator.of(context).pop();
},
child: CircleAvatar(
child: Icon(Icons.close),
backgroundColor: Colors.red,
),
),
),
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: MyTextFormField(
hintText: 'First Name',
validator: (String value) {
if (value.isEmpty) {
return 'Enter your first name';
}
return null;
},
onSaved: (String value) {
widget.tempModel.firstName = value;
},
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: MyTextFormField(
hintText: 'Last Name',
validator: (String value) {
if (value.isEmpty) {
return 'Enter your last name';
}
return null;
},
onSaved: (String value) {
print(value);
widget.tempModel.lastName = value;
},
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: MyTextFormField(
hintText: 'Enter email',
isEmail: true,
// validator: (String value) {
// if (!validator.isEmail(value)) {
// return 'Please enter a valid email';
// }
// return null;
// },
onSaved: (String value) {
widget.tempModel.email = value;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text("Submit"),
onPressed: () {
// var m = widget.tempModel;
// print(m.firstName + "" + m.lastName + "" + m.email);
// return;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
// var m = widget.tempModel;
// print(m.firstName + "" + m.lastName + "" + m.email);
widget.models.add(Model.fromModel(widget.tempModel));
setState(() {
widget.models = widget.models;
// widget.tempModel.add(new widget.models());
}
);
Navigator.of(context).pop();
}
},
),
)
],
)
),
],
),
);
}
);
}
),
alignment: Alignment.bottomRight,
),
],
),
),
)
);
}
}
class MyTextFormField extends StatelessWidget {
final String hintText;
final Function validator;
final Function onSaved;
final bool isPassword;
final bool isEmail;
MyTextFormField({
this.hintText,
this.validator,
this.onSaved,
this.isPassword = false,
this.isEmail = false,
});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
decoration: InputDecoration(
hintText: hintText,
contentPadding: EdgeInsets.all(15.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[200],
),
obscureText: isPassword ? true : false,
validator: validator,
onSaved: onSaved,
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
),
);
}
}

How to validate formfield

Am a newbie though. I followed a tutorial for my code below which is a register form. How can i validate each input field since it's just one widget which is reused for the entire input field.
............................................................................................................................................................
Code
import 'package:flutter/material.dart';
import 'package:flutterlogindesign/utils/color.dart';
import 'package:flutterlogindesign/widgets/btn_widget.dart';
import 'package:flutterlogindesign/widgets/herder_container.dart';
class RegPage extends StatefulWidget {
#override
_RegPageState createState() => _RegPageState();
}
class _RegPageState extends State<RegPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.only(bottom: 30),
child: Column(
children: <Widget>[
HeaderContainer("Register"),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 30),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_textInput(hint: "Fullname", icon: Icons.person),
_textInput(hint: "Email", icon: Icons.email),
_textInput(hint: "Phone Number", icon: Icons.call),
_textInput(hint: "Password", icon: Icons.vpn_key),
Expanded(
child: Center(
child: ButtonWidget(
btnText: "REGISTER",
onClick: () {
Navigator.pop(context);
},
),
),
),
RichText(
text: TextSpan(children: [
TextSpan(
text: "Already a member ? ",
style: TextStyle(color: Colors.black)),
TextSpan(
text: "Login",
style: TextStyle(color: orangeColors)),
]),
)
],
),
),
)
],
),
),
);
}
Widget _textInput({controller, hint, icon}) {
return SingleChildScrollView(
child: Container(
margin: EdgeInsets.only(top: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10),
child: TextFormField(
controller: controller,
decoration: InputDecoration(
border: InputBorder.none,
hintText: hint,
prefixIcon: Icon(icon),
),
),
),
);
}
}
Use Form Widget like the following
final _formKey = GlobalKey<FormState>();
bool autoValidate = false;
String phone;
child:Form( key: _formKey,
autovalidateMode: autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,
child: Column(
children: [
AppTextFormField(
initialValue: phone,
onChanged: (value) {
phone = value;
},
validator: (value) {
if (value.isEmpty) {
return 'Enter Phone number';
}
},
),
PrimaryButton(
text: 'Go',
onTap: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
} else {
autoValidate = true;
}
},
),
],
),
),

Flutter textfield onChanged don't work when textfield bring value from controller

I'm working on flutter project and came across a problem. the textfield supposed to take a value from controller which work perfectly but onChanged function wont work. However it is not working.i must retype value to show results .
how can i get result from onchanged when my textfield brings the value ?
code:
// search function that call api
class _SearchPageTState extends State<SearchPageT> {
GlobalState _store = GlobalState.instance;
List<dynamic> searchResults = [];
searchT(value) async {
SearchServicet.searchApiT(value).then((responseBody) {
List<dynamic> data = jsonDecode(responseBody);
setState(() {
data.forEach((value) {
searchResults.add(value);
});
});
});
}
#override
///////
//code textfield search onchanged
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
centerTitle: true,
),
body: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
autofocus: true,
controller: TextEditingController()
..text = '${_store.get('num')}',
onChanged: (value) {
searchResults.clear();
searchCodeighniterT(value);
},
textAlign: TextAlign.center,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 25.0),
labelText: 'number',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: null,
),
),
),
),
SizedBox(
height: 10.0,
),
ListView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
itemCount: searchResults.length,
itemBuilder: (BuildContext context, int index) {
return buildResultCard(context, searchResults[index]);
},
),
],
),
),
);
}
//here where shows the result
Widget buildResultCard(BuildContext context, data) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
new Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bgwlgo.png"), fit: BoxFit.cover),
),
margin: EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
new Card(
child: ListTile(
title: Text(
"DATE:",
),
subtitle: Text(
data['DATETIME'].toString(),
),
),
),
new Card(
child: ListTile(
title: Text(
"TRAITEMENT:",
),
subtitle: Text(
data['TRAITEMENT_DETAIL'].toString()
),
),
),
new Padding(
padding: EdgeInsets.all(9.0),
),
],
),
),
Divider(
color: Colors.black,
)
],
),
);
}
As discussed and understood in the comments, here are a couple of possible solutions for the issue.
If you are using a stateful Widget and need a controller for your TextFormField, you can use it to set the text on the TextFormField. Otherwise, you can just use the initialValue property:
class TextFieldIssue64061076 extends StatelessWidget {
final TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Text('Page 1'),
TextFormField(
controller: _textEditingController,
),
FlatButton(
child: Text('Submit'),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return SecondPage64061076(text: _textEditingController.text);
}
)),
),
],
);
}
}
class SecondPage64061076 extends StatefulWidget {
final String text;
SecondPage64061076({
this.text
});
#override
_SecondPage64061076State createState() => _SecondPage64061076State();
}
class _SecondPage64061076State extends State<SecondPage64061076> {
final TextEditingController _textEditingController = TextEditingController();
#override
void initState() {
// You can either use a text controller to set the text on the text field
// or the initialValue below
if(widget.text != null && widget.text != ''){
_textEditingController.text = widget.text;
methodToCallOnChanged(widget.text);
}else{
_textEditingController.text = '';
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Page 2'),
TextFormField(
controller: _textEditingController,
onChanged: (value) => methodToCallOnChanged(value),
// As mentioned you could just use the initial value, it you don't need
// a Stateful Widget
// initialValue: widget.text ?? '',
),
]
),
);
}
void methodToCallOnChanged(data){
print('I was called onChange or when the view opened and there was data');
}
}
Widget build(BuildContext context) {
bool isRecording = false;
bool isShowSendButton = false;
/// make sure textcontroller and any variabloes or booleans are not defined
///in the build method
}
You can't be using the constructor of the TextEditingController and assign it to the controller.
The controller of the TextField only takes the variable assigned to the TextEditingController. Check the following code.
controller:theNameOfYourController
Expanded(
flex: 8,
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 10),
child: TextFormField(
onChanged: (value){
messageFieldController.text=value;
},
//controller: messageFieldController,
minLines: 1,
maxLines: 2,
textCapitalization: TextCapitalization.sentences,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
prefixIcon: IconButton(
onPressed: () {},
icon: const Icon(Icons.add, color: Colors.blue),
),
suffixIcon: processing == true
? const CircularProgressIndicator()
: IconButton(
onPressed: () {
try {
/*for (int i = 0;
i < widget.selectedMembers.length;
i++) {
sendMessage(
widget.selectedMembers[i].number);
}*/
for (int i = 0;
i < widget.selectedGroups.length;
i++) {
if (widget.selectedGroups.isNotEmpty) {
sendMessageToGroup(
widget.selectedGroups[i].id,
widget.selectedGroups[i].groupName);
}
}
} catch (err) {
Fluttertoast.showToast(
msg: 'Unable to send Message');
setState(() {
processing = false;
});
}
},
icon:
const Icon(Icons.send, color: Colors.blue),
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(50),
),
),
),
),
),
)

How to make wrap content for ListView

I need to make dialog with form input fields and when i use with column content is fit to screen but when i try to type values it hiding the below input fields and submit button.Show to solve this issue i only know one soluction that replacing column with listview and works it allow me to scrool but the content is not fit to screen. How to make the content in listview fit to sceen?
Here is my full code
import 'package:devaayanam/Confi.dart';
import 'package:flutter/material.dart';
class BookPujaDialogContent extends StatefulWidget {
BookPujaDialogContent({Key key}) : super(key: key);
#override
_BookPujaDialogContentState createState() => _BookPujaDialogContentState();
}
class _BookPujaDialogContentState extends State<BookPujaDialogContent> {
final _formKey =GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Container(
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: Confi.TEMPLENAME
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter '+Confi.TEMPLENAME;
}
return null;
},
),
TextFormField(
decoration: InputDecoration(
labelText: Confi.DEITY
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter '+Confi.DEITY;
}
return null;
},
),
TextFormField(
decoration: InputDecoration(
labelText: Confi.BN
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter '+Confi.BN;
}
return null;
},
),
TextFormField(
decoration: InputDecoration(
labelText: Confi.STAR
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter '+Confi.STAR;
}
return null;
},
),
Container(
margin: EdgeInsets.only(top: 20),
child: RaisedButton(
onPressed: () {
// Validate returns true if the form is valid, or false
// otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid, display a Snackbar.
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Processing Data')));
}
},
textColor: Colors.white,
padding: const EdgeInsets.all(0.0),
shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0D47A1),
Color(0xFF1976D2),
Color(0xFF42A5F5),
],
),
borderRadius: BorderRadius.all(Radius.circular(10.0))
),
width: MediaQuery.of(context).size.width,
height: 40,
// padding: const EdgeInsets.fromLTRB(45, 10, 45, 10),
child: Center(
child: Text(
Confi.BOOKNOW,
style: TextStyle(fontSize: 16)
),
),
),
),
)
],
),
),
);
}
}
Set shirinkWrap: true in ListView.
Dialog(
child: Form(
key: _formKey,
child: ListView(
shrinkWrap: true, //TODO: Use this
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: Confi.TEMPLENAME),
validator: (value) {
if (value.isEmpty) {
return 'Please enter ' + Confi.TEMPLENAME;
}
return null;
},
),
....
....