Search code examples
flutterdartflutter-getx

How to retrieve a TextEditingController inside a Controller layer with Getx?


I have this statement in my View layer

TextEditingController controllerDestino = TextEditingController();

And I want to recover this controllerDestino, to use within a method that is in my Controller layer.

 statusUberNaoChamado() {
showBoxAdress = true;

changeMainButton("Chamar", Color(0xFF1ebbd8), () {
  callUber("I need pass the controller here");
});

update();}

Thank you in advance for your attention :)


Solution

  • Define/instantiate the TextEditingController as a field inside your GetxController you're using to control your form / implement business logic.

    class DestinoFormControllerX extends GetxController {
      static DestinoFormControllerX get i => Get.find();
      final GlobalKey<FormBuilderState> key = GlobalKey<FormBuilderState>();
    
      // ↓ place the text editing controller inside your... controller :)
      var controllerDestino = TextEditingController();
    

    And use the TextEditingController values wherever you need in your GetxController

      void resetForm() {
        key.currentState.reset();
        controllerDestino.text = '';
        focusNode.requestFocus();
      }
    

    In your View layer, inject your GetxController, and get the text editing controller & access any other methods/fields you need.

    class DestinoForm extends StatelessWidget {
      final void Function() submitHandler;
    
      DestinoForm({this.submitHandler});
    
      @override
      Widget build(BuildContext context) {
        final dcx = Get.put(DestinoFormControllerX());
        // ↑ inject GetxController, be careful to put *inside* build method
    
        return FormBuilder(
          key: dcx.key,
          child: Column(
            children: [
              FormBuilderTextField(
                name: 'destino',
                controller: dcx.controllerDestino,
                decoration: InputDecoration(
                  labelText: 'Destino',
                ),
    

    Most forms would have Reset & Submit buttons. There you can call methods on your GetxController....

          actions: [
            FlatButton(
              child: Text('Reset'),
              onPressed: () => DestinoFormControllerX.i.resetForm(),
            ),
    

    Side Note

    If you're instantiating / injecting your GetxController in your Form Widget with Get.put(), do so inside the build method of your Form Widget.

    Otherwise, you'll likely have TextEditingControllers calling setState on a StatefulWidget (the textfield) that is no longer mounted in the widget tree:

    ════════ Exception caught by foundation library ════════════════════════════════════════════════════
    The following assertion was thrown while dispatching notifications for TextEditingController:
    setState() called after dispose(): _FormBuilderTextFieldState#96390(lifecycle state: defunct, not mounted)
    

    Good

    class DestinoForm extends StatelessWidget {
      final void Function() submitHandler;
    
      DestinoForm({this.submitHandler});
    
      @override
      Widget build(BuildContext context) {
        final dcx = Get.put(DestinoFormControllerX());
        // ↑ inject GetxController, be careful to put *inside* build method
    
    

    Bad

    class DestinoForm extends StatelessWidget {
      final void Function() submitHandler;
      final dcx = Get.put(DestinoFormControllerX());
      // ↑ wrong place, DestinoFormControllerX gets linked to previous route
    
      DestinoForm({this.submitHandler});
    
      @override
      Widget build(BuildContext context) {
    
    

    More detail on Github, mentioning proper injection / usage of GetX.