How to clear TextFormField's on a form in Flutter? - flutter

I have a form that contains 3 TextFormFields. I have a "save" button and a "cancel" button. If the user clicks "cancel" I want to clear the TextFormFields. Can anyone tell me how to do this? Thanks.
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Text(
'Display Name',
style: _style,
textAlign: TextAlign.right,
),
SizedBox(height: 5),
TextFormField(
autofocus: true,
initialValue: _displayName,
validator: (value) {
if (value.isEmpty) {
return 'please enter your display name';
}
return null;
},
onSaved: (value) {
_displayName = value;
},
decoration: _textFormFieldDecoration(
hintText: 'your display name',
padding: 12.0,
),
),
...
RaisedButton(
color: kMainColor80,
child: Text('Cancel', style: TextStyle(color: Colors.white, fontSize: 16)),
onPressed: () {
setState(() {
_displayName = '';
_mobileNumber = '';
_emailAddress = '';
});
},
),

You can use the controller.
So, your code should be like:
1st, initialize TextEditingController variable somewhere inside the top of your class:
final myController = TextEditingController();
And then put that controller inside each TextFormField. (Note: I only see your first TextFormField in the code you provided. So, I only put it once. Make sure to put it on each TexFormField)
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Text(
'Display Name',
style: _style,
textAlign: TextAlign.right,
),
SizedBox(height: 5),
TextFormField(
controller: myController, // PUT HERE
autofocus: true,
initialValue: _displayName,
validator: (value) {
if (value.isEmpty) {
return 'please enter your display name';
}
return null;
},
onSaved: (value) {
_displayName = value;
},
decoration: _textFormFieldDecoration(
hintText: 'your display name',
padding: 12.0,
),
),
And then, inside the button, call that controller:
RaisedButton(
color: kMainColor80,
child: Text('Cancel', style: TextStyle(color: Colors.white, fontSize: 16)),
onPressed: () {
setState(() {
myController.clear();
});
},
),
If you want each TextFormField to have their own controller, you can create 3 different controllers variable. And thet call each one of them inside you button

you need to add a controller to your TextFormField:
TextFormField(
controller: nameController,
decoration: kTextFieldDecoration.copyWith(
labelText: 'name',
icon: Icon(FontAwesomeIcons.user),
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter Name';
}
return null;
},
),
on your setState()
setState(() {
nameController.text = "";
});

You have to add controller to each text field final TextEditingController _nameController = TextEditingController();
Pass your controller to the text field controller: _nameController,
Now you can clear your text form field using _nameController.clear()

you can do this very easy. just use a TextEditingController like this :
#override
void initState() {
super.initState();
this.display_name_field = new TextEditingController();
}
and when you click on cancel btn you can run this :
this.display_name_field.clear();
I hope I was able to help.

Related

Add new text form field when button pressed?

I have screen which have username field,
Here, When i press the submit button add new TextFormField below the UserName field so how i can do this?
Code as Below.
return Container(
child: Form(
key: _formKey,
child: Column(
children: [
Container(
padding: const EdgeInsets.all(10),
child: Text("Reset Password"),
),
Container(
child: Center(
child: Expanded(
child: Text(
"Enter your username below to recieve password reset instruction",
textAlign: TextAlign.center,
maxLines: 2,
),
),
),
),
TextFormField(
controller: userNameController,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "User Name",
),
focusNode: fnField1,
validator: (value) {
if (value?.isEmpty == true) {
return AppLocalizations.of(context)!.valEnterUserName;
}
return null;
},
),
Container(
constraints: const BoxConstraints(minWidth: double.infinity),
child: ElevatedButton(
onPressed: () async {},
child: Text("Submit"),
),
),
],
),
),
);
Please help me that how i can do this.
In such a case we can use a StatefulWidget to set a _displayNewTextField boolean to true once the button is pressed:
bool _displayNewTextField = false;
...
Container(
constraints: const BoxConstraints(minWidth: double.infinity),
child: ElevatedButton(
onPressed: () async {
setState(() {
_displayNewTextField = true;
});
},
child: const Text("Submit"),
),
),
And use a Visibility Widget to show the new TextField accordingly:
Visibility(
visible: _displayNewTextField,
child: TextFormField(
controller: newTextFieldController,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
labelText: "User Name",
),
),
),
A full example is reported below:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _displayNewTextField = false;
TextEditingController newTextFieldController = TextEditingController();
TextEditingController userNameController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Form(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(10),
child: const Text("Reset Password"),
),
const Center(
child: Expanded(
child: Text(
"Enter your username below to recieve password reset instruction",
textAlign: TextAlign.center,
maxLines: 2,
),
),
),
TextFormField(
controller: userNameController,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
labelText: "User Name",
),
),
Visibility(
visible: _displayNewTextField,
child: TextFormField(
controller: newTextFieldController,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
labelText: "User Name",
),
),
),
Container(
constraints: const BoxConstraints(minWidth: double.infinity),
child: ElevatedButton(
onPressed: () async {
setState(() {
_displayNewTextField = true;
});
},
child: const Text("Submit"),
),
),
],
),
),
),
);
}
}

Error: The parameter 'onSubmit' can't have a value

Hi I have created a default form field, in a separate dart file called components, and I have login_screen.dart also.
there are many errors I don't know how to fix it, and make the code work, I will put down the code of the component.dart code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
Widget defaultButton(
{double width = double.infinity,
Color background = Colors.blue,
double radius = 10.0,
required Function function,
required String text,
bool isUpperCase = true}) =>
Container(
height: 40.0,
width: width,
child: MaterialButton(
onLongPress: () {},
onPressed: function(),
child: Text(
isUpperCase ? text.toUpperCase() : text.toLowerCase(),
style: TextStyle(color: Colors.white),
)),
decoration: BoxDecoration(
borderRadius: BorderRadiusDirectional.circular(radius),
color: background,
),
);
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function onSubmit,
Function onChange,
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit(),
onChanged: onChange(),
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);
and here is the code of the login_screen.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:udemy_flutter/shared/components/components.dart';
class LoginScreen extends StatelessWidget {
var emailController = TextEditingController();
var passController = TextEditingController();
var formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold
),
),
const SizedBox(
height: 40.0,
),
defaultFormFeild(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value){
if(value.isEmpty != null){
return 'Email Cannot Be Empty';
}
return null;
}
),
const SizedBox(
height: 15.0,
),
TextFormField(
controller: passController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
prefixIcon: Icon(
Icons.lock
),
suffixIcon: Icon(
Icons.remove_red_eye,
)
),
onChanged: (value) {
print(value);
},
onFieldSubmitted: (value) {
print(value);
},
validator: (value) {
if(value!.isEmpty){
return 'Password cannot be empty';
}
return null;
},
),
const SizedBox(
height: 10.0,
),
defaultButton(
function: (){
print(emailController.text);
print(passController.text);
},
text: 'Login',
),
const SizedBox(
height: 10.0,
),
defaultButton(
text: 'ReGister',
function: () {
print('You have just clicked on register');
},
background: Colors.red,
isUpperCase: false
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Don\'t you have an account?'),
TextButton(onPressed: () {}, child: const Text(
'Register Now'
))
],
)
],
),
),
),
),
),
);
}
}
Idk if all the problems came from a null-safety feature in a flutter because I'm new in this technology.
Why
The reason this happens is because with null safety enabled, your functions onSubmit and onChange can't be null.
Solution
I would do it this way:
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit, //Add question mark
Function? onChange, //Add question mark
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit != null? onSubmit() : null, //do null checking
onChanged: onChange != null? onChange() : null, //do null checking
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);

how to get save the value from textfromfield and pass it back to page?

import 'package:flutter/material.dart';
import 'package:mmitra/widgets/header.dart';
import 'home.dart';
class CreateAccount extends StatefulWidget {
#override
_CreateAccountState createState() => _CreateAccountState();
}
class _CreateAccountState extends State<CreateAccount> {
late String username;
final _key = Global Key<FormState>();
#override
Widget build(BuildContext parentContext) {
return Scaffold(
appBar: header(context, titleText: 'Create Account'),
body: ListView(children: [
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 25),
child: Center(
child: Text(
'Create a username',
style: TextStyle(fontSize: 25.0),
),
),
),
Padding(
padding: EdgeInsets.all(16.0),
child: Form(
child: TextFormField(
key: _key,
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
GestureDetector(
onTap: () {
_key.currentState!.save();
Navigator.pop(context, username
);
},
child: Container(
height: 50,
width: 300,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(7)),
child: Center(
child: Text(
'Submit',
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
),
],
),
),
]),
);
}
}
and I'm getting below shown errors:
Exception caught by gesture
The following Cast Error was thrown while handling a gesture
Null check operator used on a null value
I just want to get the textfromfield value and i want to pass it to the home.dart page in order to create the document in firebase collection
you must define a EditTextControll() ex:textController and set it to TextFormField to controller paramerter , and then get text as textController.text and pass with Navigatoer .
for pass wihtin first screen to two screen
Firstly /
TextEditingController controller = TextEditingController();
Secoundly /
body: Form(
child: TextFormField(
controller: controller,
onTap: (){
//here SettingsScreen() is example
// name is paramerter in the secound screen
Navigator.push(context,
MaterialPageRoute(builder: (context)=>SettingsScreen(name:controller.text),),
);
},
),
),
You added key in TextFormField
Form(
child: TextFormField(
key: _key,
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
Remove it from TextFormField and Add it in Form
Just Like:
Form(
key: _key,
child: TextFormField(
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
This will Solve your Issue.

How to save int data from TextFormField in Flutter

I made some TextFormField, and I want to save the data in int when I press the FlatButton. When I press FlatButton, I want him to check whether the sum of TextFormField expenses and savings is not greater than TextFormField income. if the sum of the TextTormField expenses and savings is greater, I want to display errortext under the textformfield savings "your expenses and savings are greater than your income"
class BigNotePage extends StatefulWidget {
#override
_BigNotePageState createState() => _BigNotePageState();
}
class _BigNotePageState extends State<BigNotePage> {
final _formKey = GlobalKey<FormState>();
String _income;
String _expenses;
String _savings;
#override
Widget build(BuildContext context) {
return Container(
padding: kPading,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitlePage('Big Note'),
Expanded(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TxtField(
label: 'Income',
function: (value) => _income = value,
),
TxtField(
label: 'Expenses',
function: (value) => _expenses = value,
),
TxtField(
label: 'Savings',
function: (value) => _savings = value,
),
FlatButton(
onPressed: () {
int.parse(_income) >=
int.parse(_expenses) + int.parse(_savings)
? _formKey.currentState.save()
: print('null');
},
child: Text(
'WRITE THAT',
style: TextStyle(letterSpacing: 1.25),
),
color: Colors.yellow,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
),
],
),
),
),
Container(
width: 250.0,
child: Text(
'*if you get another income for this mounth, input the income again.',
style: TextStyle(fontSize: 12.0),
),
),
],
),
);
}
}
class TxtField extends StatelessWidget {
TxtField({this.label, this.function});
final String label;
final Function function;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: TextFormField(
onSaved: function,
keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: label,
prefix: Container(
padding: EdgeInsets.all(8.0),
child: Text(
'IDR',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
),
),
),
);
}
}
Replace String values to the controller values
final _incomeController = TextEditingController();
final _expenseController = TextEditingController();
final _savingController = TextEditingController();
Also, add
bool _validate = false;
Convert String value to int of your TextField:
TextField(
controller: _incomeController,
label: 'Income',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
TextField(
controller: _expenseController ,
label: 'Expenses',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
TextField(
controller: _savingController,
label: 'Savings',
decoration: InputDecoration(
errorText: _validate ? 'Your message' : null,
),
),
Now FlatButton Logic:
onPressed: () {
String _income = _incomeController.text;
String _expenses = _expenseController.text;
String _savings = _savingController.text;
int.parse(_income) >=
int.parse(_expenses) + int.parse(_savings)
? _formKey.currentState.save()
: print('null');
},
Rest apply your logic wherever you want.

TextFormField losing value when changing focus

I am trying to move to other TextFormField but whenever I lose focus from first TextFormField text became empty, I search about this issue but I don't find any solution till now.
var _formKey = GlobalKey<FormState>();
Note note;
TextEditingController titleController=TextEditingController();
TextEditingController descriptionController=TextEditingController();
#override
Widget build(BuildContext context) {
TextStyle textStyle=Theme.of(context).textTheme.title;
titleController.text=note.title;
descriptionController.text=note.description;
// TODO: implement build
return WillPopScope(
onWillPop: (){
moveToLastScreen();
},
child:Scaffold(
appBar: AppBar(
title: Text("appBarTitle"),
leading: IconButton(icon:Icon(Icons.arrow_back),onPressed: (){
moveToLastScreen();
},),
),
body: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.only(top: 15.0,left: 15.0,right: 10.0),
child: ListView(
children: <Widget>[
//1st element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){
if(value.isEmpty)
{
return "Please enter Title";
}
},
controller: titleController,
style: textStyle,
onSaved: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},
/*onChanged: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},*/
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//2nd element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){ //2nd step for form with validation
if(value.isEmpty)
{
return "Please enter principle amount";
}
},
onSaved: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},
controller: descriptionController,
style: textStyle,
/*onChanged: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},*/
decoration: InputDecoration(
labelText: "Description",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//3th element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Save",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
if(_formKey.currentState.validate()) {
debugPrint("Save Pressed");
_save();
}
});
}
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Delete",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
debugPrint("Delete Pressed");
_delete();
});
}
),
),
],
),
),
],
),
)),
));
}
Please suggest me I am new in flutter.
Remove titleController.text=note.title; descriptionController.text=note.description; from your build method and place it in initState method.
You will lose the value in the textField because those lines get executed anytime there is a rebuild, thereby replacing the values gotten from the textFields and replacing it with note.title and note.description which are empty at that point.
In other words, remove those lines and add this to your code.
#override
void initState() {
super.initState();
titleController.text=note.title;
descriptionController.text=note.description;
}