i have some questions about which is the correct way of creating TexEditingController;
Assuming that i want to create a controller with a fixed text, so i can do like this :
TextEditingController bioEditorController = new TextEditingController(text:"dummy");
Now my questions is this:
if i'm usign a stateful widget i can create this controller ad assign an initial text by doing this :
TextEditingController bioEditorController;
@override
void initState() {
bioEditorController = new TextEditingController(text: "dummy");
super.initState();
}
but if i'm not using a stateful widget is it correct to make something like this :
@override
Widget build(BuildContext context) {
TextEditingController bioEditorController =
new TextEditingController(text: controller.profile.value.bio);
What i mean is it correct to create this controller inside the build method, if i do like this it works , but i think that probably is not the best way of doing this things, also becauze i know that controller should also disposed....
I really need some help about clarifying this. Thanks
Solution 1: Loren.A
You are correct in assuming that doing that in the build method is not ideal. You have way less control over how many times the build method runs vs initState
.
And while it's generally true that you would need a stateful widget when dealing with TextEditingControllers (or hooks), if you use GetX state management it's absolutely fine, and preferred to not bother with a stateful widget just because you need a TextEditingController
.
Another benefit of this way is very easy access to the value of the TextEditingController
from anywhere else in the app.
Here's a quick example. This is a class where you can keep all your TextEditingControllers
.
class TextController extends GetxController {
RxString textfieldString = ''.obs; // observable String
TextEditingController textController;
// this onInit replaces initState of a stateful widget
@override
onInit() {
super.onInit();
textController = TextEditingController(text: 'dummy');
// adding a listener that automatically updates the textfieldString with the textfield value
textController.addListener(() {
textfieldString.value = textController.text;
debugPrint(textfieldString.value);
});
}
}
Initialize the controller in your main or anytime before you actually use it. This is when the onInit
from that class is called.
Get.put(TextController()).textController;
Here's Page1
a stateless widget with an already initialized TextEditingController
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.find<TextController>(); // finding same initialized controller
return Scaffold(
body: Center(
child: TextFormField(
controller: controller.textController, // using TextEditingConroller from GetX class
),
),
);
}
}
And here's a quick example of a text widget on a different page automatically updating anytime the user types into the TextFormField
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller =
Get.find<TextController>(); // finding same instance of controller
return Scaffold(
body: Center(
// this Obx widget rebuilds based on any updates
child: Obx(
() => Text(controller.textfieldString.value),
),
),
);
}
}
So no matter where you are in your app, you can access the value of that TextFormField
and you don't have to use a stateful widget. The GetxController
will be removed from memory when not in use.
At this point the only time I ever need to use a stateful widget is when I need the AutomaticKeepAliveClientMixin
.
Even animations can be done with stateless widgets in GetX by adding SingleGetTickerProviderMixin
to a Getx class and doing everything there that would normally clutter up your stateful widget.