LorenzoBerti
LorenzoBerti

Reputation: 6974

Disabled button when textInputField is invalid on change text Flutter

I'm new on Flutter. I'm trying to disabled button while I compile textFormField and it is invalid. My problem is that it works only if I click on "confirm" on keyboard and not while I compile my input. So would like disable button while I write the input.

I've done a pastebin for example:

https://pastebin.com/q5WuwrCm

class AddCartButton extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return AddCartButtonState();
  }
}
class AddCartButtonState extends State<AddCartButton>{
  TextEditingController myController = TextEditingController();
  bool isValid = false;
  @override
  Widget build(BuildContext context) {
    void _addToCart(){
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text("QUANTITY"),
            content: Column(
              children: <Widget>[
                TextFormField(
                    controller: myController,
                    decoration: new InputDecoration(labelText: "quantity"),
                    keyboardType: TextInputType.numberWithOptions(decimal: true),
                    inputFormatters: <TextInputFormatter>[],
                    autovalidate: true,
                    validator: (value) {
                      if (value.isEmpty) {
                        isValid  = false;
                        return "the quantity cannot be empty";
                      } else if (double.tryParse(value) == null) {
                        isValid = false;
                        return "the quantity must be valid number";
                      } else {
                        isValid = true;
                        return null;
                      }
                    }
                )
              ],
            ),
            actions: <Widget>[
              FlatButton(
                  disabledTextColor: Colors.grey,
                  child: Text("add"),
                  onPressed: isValid ? () { print("is valid"); }: null
              )
            ],
          );
        },
      );
    }
  }
}        

Upvotes: 1

Views: 3596

Answers (3)

Shailendra Rajput
Shailendra Rajput

Reputation: 2982

You can use this method .

  bool isEnable = false;
void validateButton() {
    bool isValid = true;

    isValid = userEmail.isNotEmpty &&
        userPassword.isNotEmpty &&
        validateEmail(userEmail) &&
        userPassword.length >= 8;

    setState(() {
      isEnable = isValid;
    });
  }

now in your Textfield onChanged method you have to call this function

like This

onChanged: (email) {
                        userEmail = email;
                        setState(() {});
                        validateButton();
                      },

and in your Login Button

isEnable?ActiveButton():DisableButton()

Upvotes: 0

Ademir Villena Zevallos
Ademir Villena Zevallos

Reputation: 1561

You can use addListener() function on your TextEditingController myController.

myController.addListener((){
    //With this, you can "listen" all the changes on your text while
    //you are typing on input
    print("value: ${myController.text}");
    //use setState to rebuild the widget
    setState(() {
        //you can check here if your text is valid or no
        //_isValidText() is just an invented function that returns
        //a boolean representing if the text is valid or not
        if(_isValidText(myController.text)) isValid = true;
        else isValid = false;
    });
});

Upvotes: 2

J. S.
J. S.

Reputation: 9635

If I understood what you want to achieve the following code works for you. The conditions I set are the same as your validation rules:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController _textEditingController = TextEditingController();
  Function _submitFunction;
  // We need a reusable timer and it needs to not be null so that we can cancel it from th start.
  Timer _timer = Timer(Duration(milliseconds: 1), () => print('initialTimer'));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Auto disable button'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextFormField(
                controller: _textEditingController,
                onChanged: (text) {
                  setState(() {
                    _submitFunction = null;
                  });
                  restartTimer();
                },
              ),
              RaisedButton(
                child: Text('Submit'),
                onPressed: _submitFunction,
              ),
            ],
          ),
        ),
      )
    );
  }

  void submitForm(){
    print(_textEditingController.text);
  }

  void enableButton(){
    if(_textEditingController.text != ''){
      setState(() {
        _submitFunction = submitForm;
      });
    }
  }

  void restartTimer(){
    _timer.cancel();
    _timer = Timer(Duration(milliseconds: 1500), enableButton);
  }
}

Upvotes: 0

Related Questions