skip to Main Content

The Problem

The isEmpty check is returning true for a non-empty String field. My guess is – TextEditingController’s String metadata is not updating with string update from an async load.

  1. I’m not sure if I’m missing something obvious or if this is a Dart/Flutter bug.
  2. Is there an idiomatic way to accomplish this check?

Here’s my code

  var textController = TextEditingController();

  @override
  void initState() {
    super.initState();
    init();
  }

  void init() async {
    final foo = await FooProvider.instance.getFoo(widget.uuid);
    textController.text = foo.title;
  }

The actual usage of the textController,


GestureDetector(
                onTap: textController.text.isEmpty
                    ? () {
                        debugPrint('Empty - ${textController.text}');
                      }
                    : () {
    // rest of the code

Output
(With actual field value "abc")
enter image description here

2

Answers


  1. If you change the text of TextEditingController, your widget wouldn’t be rebuilt automatically.

    Because setState never has been called.

    Solution

    1. (Recommended) Wrap textController with ValueListenableBuilder if you want to listen value changing.
    ValueListenableBuilder(
          valueListenable: textController,
          builder: (context, value, child) {
            return GestureDetector(
              onTap: textController.text.isEmpty
                  ? () {
                debugPrint('Empty - ${textController.text}');
              }
                  : () {},
            ); 
          },
        );
    
    1. (Not recommended) Call setState manually if textController value changed.

    This will rebuild entire widget tree of your widget.

      void init() async {
        final foo = await FooProvider.instance.getFoo(widget.uuid);
        
        setState((){
          textController.text = foo.title;
        });
      }
    
    1. Evaluate isEmpty in GestureDetector.onTap

    by @Ivo ‘s comment you can check isEmpty in onTap. This works because isEmpty is evaluated at time onTap called.

    GestureDetector(
              onTap: () {
                if(textController.text.isEmpty) return;
                // not empty
              },
            )
    
    Login or Signup to reply.
  2. An alternative solution is to do the check inside a single implementation of onTap instead of two different ones, like this

    GestureDetector(
                onTap: () {
                        if (textController.text.isEmpty) {
                          debugPrint('Empty - ${textController.text}');
                        } else {
                          // rest of the code
                        }
                      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search