I am trying to use TextFormField in a stateless widget along with ScopedModel to deal with text in it and facing various issues as follow.
I tried using controller for field, but everytime I enter some text and press done on keyboard, text gets cleared. No idea as to why.
If I remove controller, text stays in field but new problem gets created as to how to get text from field. I solved it by using callback onFieldSubmitted.
But turns out, onFieldSubmitted is only getting called when we click on done button on keyboard. If I enter text in field and instead of clicking ok, click on another field, callback won't get called and I will have no way of tracking what user has entered in field.
Any solution for this?
Attaching sample code for issue.
class LoginPageStateless extends StatelessWidget {
final loginUsernameController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: true,
body: ScopedModelDescendant<AccountModel>(
builder: (context, child, model) {
return Form(
//key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
style: TextStyle(fontSize: 15.0),
decoration: InputDecoration(
labelText: 'Email id',
hintText: '[email protected]',
),
controller: loginUsernameController,
onFieldSubmitted: model.updateLoginUsernameText,
),
TextFormField(
style: TextStyle(fontSize: 15.0),
decoration: InputDecoration(
labelText: 'Password',
),
controller: loginUsernameController,
onFieldSubmitted: model.updateLoginUsernameText,
obscureText: true,
),
],
),
);
},
),
);
}
}
You cannot and should not use Stateless
widget for storing long-term variable.
The problem is, it's exactly what you are trying to. TextEditingController
is a class instance that should be kept between renders. But by storing it into a StatelessWidget
you basically recreate it after every update.
You should instead convert your widget to Stateful
. And move that controller into the State
part
I haven't used a TextFormField
till now, I always use TextField()
for it's simplicity and flexibility. I encountered similar problem when using Redux
and stateless widgets as I have a single source of truth at the top level store. So, I had to create some callbacks inside a ViewModel
then assign that callback to the text field callback onChanged
which takes in a string param.
CustomTextWidgetWrapper(
onChangedCallback: viewModel.onChanged
),
In the TextField
wrapped in the widget I do (not giving more details):
new TextField(
controller: myController, // no use practically now
onChanged: onChangedCallback,
And in the view model I get the string and dispatch to the central storage for reuse in other widget, like a button which takes the data and sends to server
static ViewModel fromStore(Store<AppState> store) {
return new ViewModel(
onChanged: (String textFieldText) {
// I call dispatch or an API here if I want
store.dispatch(new CallAPI(params: textFieldText);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With