TextEditingController vs OnChanged

人走茶凉 提交于 2020-12-01 09:37:30

问题


I am looking for a better explanation on the benefit of TextEditingController over OnChanged event for a TextField.

My understanding is that onChanged's setState notifies all widgets of the change in state variable value. This way any widget (e.g. Text) can simply use the state variable and it will be notified of its changes.

My false hopes were TextEditingController would make it even simpler that I won't even need a state variable. Something like below:

import "package:flutter/material.dart";

class TestForm extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return TestFormState();
  }
}

class TestFormState extends State<TestForm> {
  //string myStateVariable = "";
  final ctrl = TextEditingController();

  @override
  Widget build(BuildContext context) {

    var tf = TextField(
      controller: ctrl,
    );

    var t = Text("Current value: " + ctrl.text);  // <<<<<<<<<<< false hope! doesnt work!

    var x = Column(children: <Widget>[tf,t],);

    return MaterialApp(home: Material(child: Scaffold(
      appBar: AppBar(title: Text("Test Form"),),
      body: x,
    )));
  }
}

Can anyone explain why TextEditingController or something similar cannot manage the state itself and notifies all consumers of change in state?

Thanks.


回答1:


That's not false. You are just not setting state synchronously that's all. What onChanged does is exactly possible with this approach:

class _TestFormState extends State<TestForm> {
  TextEditingController controller;

  @override
  void initState() {
    controller = TextEditingController();
    controller.addListener(() {
      setState(() {});
    });
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        Text('Current Value: ${controller.text}'),
        TextField(
          controller: controller,
        ),
      ],
    );
  }
}

As you see, we have listener that setting state everytime the controller state changes. This is exactly what onChanged does.

Edit: So, about benefits, you can achieve everything with both approach, it's a subjective way. But there are things matters:

1 - If you have BLoC pattern, you can directly assign your Stream with onChanged method.

2 - With TextEditingController you can use same controller in many place. You can achieve same thing with onChanged but it will look like workaround when someone reads your code it will look like broken code :)

3 - onChanged method is also very viable for RegEx assertion etc. It will look much cleaner comparing the controller.

At the end in my opinion, onChanged better for modularity and cleaner code in most cases. As I said it's all up to you, that's all come up my mind for now.




回答2:


TextEditingController actually is managing his own state, that's why you can see the input on the screen once you change it.

You have 2 problems here, the first is that you are not adding any listener to the TextEditingController, you are just asking "give me the current value" only when you build the widget, not "give me the value any time it changes". To achieve this you need to add a listener to the text controller and it will be called every time that the value change.

Try this :

  @override
  void initState() {
    super.initState();
    // Start listening to changes.
    ctrl.addListener(_printValue);
  }

  _printValue() {
    print("Value: ${ctrl.text}");
  }

This will work because print doesn't need to render anything on the screen but if you change it to return a widget it will not work either. That is the second problem, as you pointed out, your parent widget is not been rebuild when the value change, in this case you cannot avoid the setState (or other way to tell flutter that needs to rebuild the widget) when the value change because you need to rebuild the widget to view the change.

Another thing that ill like to point out is that TextEditingController is much powerful and it can be used for more things that just add notifiers to changes. For example if you want a button on other part of the screen that clear the text on a TextField you will need a TextEditingController binded to that field.

Hope it helps!



来源:https://stackoverflow.com/questions/56904313/texteditingcontroller-vs-onchanged

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!