0

So, I have a textwidget in my main class and I made another class that contains a TextFormField. Depending if the textfield is empty, I would like to change the color of the text from my main class.

If I put the textfield in the same class as my text widget, I'm ale to access the controller to read out if the textfield is empty or not.

Now the problem is, when I put the textfield in a seperate class I don't manage to find a way to access that controller from my main class.

I struggle a lot with passing data to and from within Dart, so hopefully this will brighten my mind.

Works when in same class

child: Text(
       'This is a Text',
        style: TextStyle(
        color: txtFieldController.value.text.isEmpty? Colors.red : Colors.green,
        ),
),

I tried with "import '' as form"; and try to access it with form.textfieldClass().txtFieldcontroller, but that doesn't seem to work.

Jaak
  • 3
  • 1

1 Answers1

0

create a property for the controller in both classes, create the controller in the main class and then pass it to the form class.

class MainWidget extends StatelessWidget {
  // create controller
  final  txtFieldController = TextEditingController();

  // pass the controller to the other class \/
  final formWidget = FormWidget(txtFieldController: txtFieldController);

  // ...
}

class FormWidget extends StatelessWidget {
  // create controller
  final TextEditingController txtFieldController;

  // ...
}

full example code:
the form widget

class FormWidget extends StatelessWidget {
  // create a property for the controller \/
  final TextEditingController txtFieldController;

  const FormWidget({Key key, this.txtFieldController}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextFormField(
        controller: txtFieldController,
      ),
    );
  }
}

the Main widget

class MainWidget extends StatefulWidget {
  @override
  _MainWidgetState createState() => _MainWidgetState();
}

class _MainWidgetState extends State<MainWidget> {
  final txtFieldController = TextEditingController();

  @override
  void initState() {
    // updates the widget on changes
    // note, the docs say: 'Avoid calling setState() high up in the tree if the change is contained to a small part of the tree.'
    // but it's not a big deal in this case
    txtFieldController.addListener(() {
      setState(() {});
    });
    super.initState();
  }

  @override
  void dispose() {
    txtFieldController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              'This is a Text',
              style: TextStyle(
                color: txtFieldController.value.text.isEmpty ? Colors.red : Colors.green,
              ),
            ),
            // pass the controller to the other class \/
            FormWidget(txtFieldController: txtFieldController)
          ],
        ),
      ),
    );
  }
}
Elfor
  • 547
  • 5
  • 10
  • Awesome, this seems to work. Let me study this further in order to understand every aspect that leads to this solution. – Jaak Feb 01 '21 at 04:35
  • So, I've implemented the solution code to my project. I notice that after every change in a textfield the entire context is rebuild (as ofcourse it is a setState), is there a more efficient way to just set the state for the text widget? Is this where keys are coming into action? I'm trying to unfold all the knowledge I absorp so far. – Jaak Feb 02 '21 at 23:55
  • @Jaak yeah this way is really inefficient, I just did it to demonstrate. you can extract whatever you want to be rebuilt to a stateful widget and listen to the changes in that widget, so it's the only one that'll be rebuilt. and maybe implement some logic to rebuild only when necessary instead of on every change. – Elfor Feb 03 '21 at 19:28