Home > Enterprise >  Showing a button to the user based on the data entered in the TextFormField
Showing a button to the user based on the data entered in the TextFormField

Time:12-06

final TextEditingController _weight = TextEditingController();

 if (_weight.text.contains(RegExp(r'[0-9]')))
        Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: BMIButton(
              onpressed: () {
                Navigator.push(
                  context,
                  PageTransition(
                      type: PageTransitionType.rightToLeft,
                      child: BMIHeight(),
                      inheritTheme: true,
                      ctx: context),
                );
              },
            ))

I'm trying to show an OutlinedButton when the user enters some data into the textFormField. When I enter a value in the TextFormField and confirm, it doesn't show a button, but when I hot reload it, it sees that value and shows the button.

CodePudding user response:

Try to add listener and call setState to update ui

 late final TextEditingController _weight = TextEditingController()
    ..addListener(() {
      setState(() {});
    });

And override the dispose method and depose this controller.

CodePudding user response:

This means you need just to update the state of your widget, first make sure this inside a StatefulWidget, then add a SetState(() {}) on the end of that method:

if (_weight.text.contains(RegExp(r'[0-9]')))
        Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: BMIButton(
              onpressed: () {
                Navigator.push(
                  context,
                  PageTransition(
                      type: PageTransitionType.rightToLeft,
                      child: BMIHeight(),
                      inheritTheme: true,
                      ctx: context),
                );
              },
            ))
           //...
           setState(() {}) // add this

CodePudding user response:

TextEditingController is implementing Listenable. You can exploit that to build part of your UI conditionally.

Moreover, TextEditingController must be correctly initialized and disposed of. You can do that smoothly with flutter_hooks.

You'd obtain this concise result:

class MyWidget extends HookWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    final textController = useTextEditingController();

    return Column(  // example, I'm not sure of what you've got there
      children: [
        TextField(controller: textController),  // Your Text Field
        ValueListenableBuilder(
          valueListenable: textController,
          builder: (context, value, child) {
            return value.text.contains(...)
                ? OutlinedButton(  // Your Button
                    onPressed: () {
                      // .. do stuff
                    },
                    child: const Text('I am ready to be pressed'),
                  )
                : const SizedBox.shrink();  // This is empty, but you can render whatever
          },
        )
      ],
    );
  }
}

CodePudding user response:

Your code that checks if the TextFormField is populated needs to be inside the build function of a stateful widget. To trigger the state update, listen to changes on the TextFormField, inside the function set the state of some variable that you can check. Add this to the initState method:

_weight.addListener(() {
    setState(() {
        _inputText = _weight.text; // Create this variable inside the state class
    });
});

And change your if statement as follows:

if (_inputText.contains(RegExp(r'[0-9]')))

Method 2

You could also Wrap your Widget with a Visibility Widget:

Visibility(
    visible: RegExp(r'[0-9]').hasMatch(_inputText),
    child: [YOUR WIDGET],
)

This still needs the listener with the setState call.

  • Related