I am trying to make a custom stateful widget work in flutter. It is called LetterTextForm, and contains some layout customization and a TextField.
I want it to be easy to retrieve the text that is entered into the TextField of the widget, with some kind of getter method in the widget body that returns TextEditingController.text. The problem is, when I make the TextEditingController controller a final variable like this:
class LetterTextForm extends StatefulWidget {
LetterTextForm({@required this.label, this.prefixIcon});
final Widget prefixIcon;
final String label;
final TextEditingController controller = TextEditingController();
String get textEntered => controller.text;
@override
_LetterTextFormState createState() => _LetterTextFormState();
}
class _LetterTextFormState extends State<LetterTextForm> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: widget.controller,
decoration: InputDecoration(
prefixIcon: widget.prefixIcon,
labelText: widget.label,
)
);
}
}
the following error is thrown: "A TextEditingController was used after being disposed."
I thought maybe the problem was that the controller shouldn't be final, so I moved the controller into the state class and made a function in the state class, textCallback, that modifies a non-final String that is in the widget class. This way works but violates widget immutability:
class LetterTextForm extends StatefulWidget {
LetterTextForm({@required this.label, this.prefixIcon});
final Widget prefixIcon;
final String label;
String text = '';
String get textEntered => text;
@override
_LetterTextFormState createState() => _LetterTextFormState();
}
class _LetterTextFormState extends State<LetterTextForm> {
var controller = TextEditingController();
void textCallback() {
widget.text = controller.text;
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
decoration: InputDecoration(
prefixIcon: widget.prefixIcon,
labelText: widget.label,
)
);
}
}
Is there a way to do this that both 1) doesn't violate immutability and 2) doesn't dispose of the TextEditingController() immediately when the user hits Enter?
It works when I get rid of the dispose() method, but that seems like it could cause some performance/memory efficiency issues later. Maybe I don't know what I'm talking about there...
Perhaps I should try something different entirely and place the TextEditingControllers further up in the tree with the ancestors of the LetterTextForm widget, and not internally within the widget?