Flutter Enable/Disable Button based on TextFormField content

一个人想着一个人 提交于 2020-12-03 11:26:51

问题


How can I activate/deactivate a button based on the content of a TextFormField?

I want to make sure a user can only press Button X if the TextFormField has 10 entered numbers (if it's a mobile number).

Thanks!


回答1:


A simple way would be to set the autovalidate property of our TextFormField to true. This will automatically detect for changes on our TextFormField widget. We can then try to check if our TextFormField's value has a String length of 10 characters on the validator property . After that we can call setState to enable or disable our button (I use FlatButton in this example).

bool _btnEnabled = false;

...

@override
Widget build(BuildContext context){

  ...

  TextFormField(

    ...
    autovalidate: true,
    validator: (String txt){
      if (txt.length == 10){
        setState((){
          _btnEnabled = true;
        });
      } else {
        setState((){
          _btnEnabled = false;
        });
      }
    }

    ...

  FlatButton(
    onPressed: _btnEnabled == true ? yourCallback : null,
    child: ...



回答2:


The state of the widget can be updated in the Form's onChanged callback which is called whenever any of the form fields' value changes. There you can use a form key to validate the form and set a flag to enable/disable the button. This solution allows you to scale to disable buttons in forms with multiple fields. For example,

/// Key used to reference the form.
final _formKey = GlobalKey<FormState>();

...

Form(
  key: _formKey,
  onChanged: () => setState(() => _enableBtn = _formKey.currentState.validate()),
  child: ListView(
    children: <Widget>[
      TextFormField(
        validator: (value) => value.length < 10 ?
          'Number must be at least 10 digits' : // return an error message
          null,
        ...
      ),
    ],
  ),
)

...

FlatButton(
  onPressed: _enableBtn ?
    () => _doSomething() :
    null, // setting onPressed to null disables the button.
  ...



回答3:


The accepted answer seems to not work using the latest Flutter v1.7.8 (stable), it gives me the following error:

This TestForm widget cannot be marked as needing to build because the framework is already in the process of building widgets

The working version looks like the following:

...
autovalidate: true,
validator: (String txt){
      bool isValid = txt.length == 10;
      if (isValid != _btnEnabled) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          setState(() {
            _btnEnabled = txt.length == 10;
          });
        });
      } 
}

...



回答4:


you can use Flutter Reactive Forms. It's a model-driven approach to handling Forms inputs and validations, heavily inspired in Angular's Reactive Forms.

It's a very simple to use libray and in the documentation there is a section that explains how to Enable/Disable Submit button based on the validity of the entire form, not just a field.




回答5:


Get error "setState() or markNeedsBuild() called during build." with accepted answer. Just add Future.delayed(Duration.zero).then(....) as a trick solution, it's working on flutter 1.12.13

TextFormField(

...
autovalidate: true,
validator: (String txt){
  if (txt.length == 10){
    Future.delayed(Duration.zero).then((_){
    setState((){
      _btnEnabled = true;
    });
  });
  } else {
    Future.delayed(Duration.zero).then((_){
    setState((){
      _btnEnabled = false;
    });
  });
  }
}
....


来源:https://stackoverflow.com/questions/53964219/flutter-enable-disable-button-based-on-textformfield-content

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