Search code examples
flutterdartcheckboxconditional-statementstextfield

Flutter - How to assign conditions to a button?


I'm creating an account creation page. It consists of some text fields, checkboxes, and an elevated button.

In the image above, That button is enabled (clickable) only if the above fields are filled and the checkboxes are enabled. Otherwise, it should be disabled (unclickable).

How to achieve this?

Code:

Column(
            children: [
              Padding(
                padding: const EdgeInsets.only(top: 35),
                child: Container(
                  width: 310,
                  child: TextFormField(
                    controller: _firstnameController,
                    decoration: InputDecoration(
                      label: RichText(
                        text: TextSpan(
                            text: 'First Name',
                            style: GoogleFonts.poppins(
                                color: Color(0xffc1c1c1),
                                fontSize: 17,
                                letterSpacing: 0.4),
                            children: const [
                              TextSpan(
                                  text: ' *',
                                  style: TextStyle(
                                    color: Colors.red,
                                    fontSize: 21,
                                  )),
                            ]),
                      ),
                    ),
                    validator: (value){
                      if(value!.isEmpty){
                        return 'This field is required';
                      }
                      return null;
                    },
                    
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Container(
                  width: 310,
                  child: TextFormField(
                    controller: _lastnameController,
                    decoration: InputDecoration(
                      label: RichText(
                        text: TextSpan(
                            text: 'Last Name',
                            style: GoogleFonts.poppins(
                                color: Color(0xffc1c1c1),
                                fontSize: 17,
                                letterSpacing: 0.4),
                            children: const [
                              TextSpan(
                                  text: ' *',
                                  style: TextStyle(
                                    color: Colors.red,
                                    fontSize: 21,
                                  )),
                            ]),
                      ),
                    ),
                    validator: (value){
                      if(value!.isEmpty){
                        return 'This field is required';
                      }
                      return null;
                    },
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Container(
                  width: 310,
                  child: TextFormField(
                    controller: _emailController,
                    keyboardType: TextInputType.emailAddress,
                    decoration: InputDecoration(
                      label: RichText(
                        text: TextSpan(
                            text: 'Enter Your Email',
                            style: GoogleFonts.poppins(
                                color: Color(0xffc1c1c1),
                                fontSize: 17,
                                letterSpacing: 0.4),
                            children: const [
                              TextSpan(
                                  text: ' *',
                                  style: TextStyle(
                                    color: Colors.red,
                                    fontSize: 21,
                                  )),
                            ]),
                      ),
                    ),
                    validator: (value){
                      if(value!.isEmpty){
                        return 'This field is required';
                      }
                      if(!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)){
                        return 'Enter a valid email';
                      }
                      return null;
                    },

                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 20),
                child: Container(
                  width: 310,
                  child: TextFormField(
                    controller: _passwordController,
                    obscureText: passwordVisible,
                    decoration: InputDecoration(
                      label: RichText(
                        text: TextSpan(
                            text: 'Enter Your Password',
                            style: GoogleFonts.poppins(
                                color: Color(0xffc1c1c1),
                                fontSize: 17,
                                letterSpacing: 0.4),
                            children: const [
                              TextSpan(
                                  text: ' *',
                                  style: TextStyle(
                                    color: Colors.red,
                                    fontSize: 21,
                                  )),
                            ]),
                      ),
                      suffixIcon: IconButton(
                      icon: Icon(passwordVisible ? Icons.visibility_off : Icons.visibility,
                      color: Color.fromARGB(255, 187, 187, 187),
                      size: 25,
                      ),
                      onPressed: (){
                        setState(() {
                          passwordVisible = !passwordVisible;
                        });
                      },
                    ),
                  ),
                  validator: (value){
                      if(value!.isEmpty){
                        return 'Please enter your password';
                      }
                      return null;
                    },
                ),
              ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 30),
                child: CheckboxListTile(
                  title: RichText(
            text: TextSpan(
              children: [
                TextSpan(
                  text: 'I have read and agree to the',
                  style: GoogleFonts.poppins(
                      color: Color(0xff000000),
                      fontSize: 15,
                      letterSpacing: 0.4,
                    ),
                ),
                TextSpan(
                  text: ' Privacy Policy.',
                  style: GoogleFonts.poppins(
                      color: Colors.blue,
                      fontSize: 15,
                      letterSpacing: 0.4,
                    ),
                    recognizer: TapGestureRecognizer()
                    ..onTap = () {
                      launchUrl(Uri.parse('https://toy-zania.com/pages/privacy-policy') );
                    }                      
                ),
                ]),
                  ),
                  
                  value: _isChecked0,
                  onChanged: (bool? newValue) {
                    setState(() {
                      _isChecked0 = newValue ?? false;
                    });
                  },
                  activeColor: Color(0xff82b235),
                  controlAffinity: ListTileControlAffinity.leading,
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 10),
                child: CheckboxListTile(
                  title: RichText(
            text: TextSpan(
              children: [
                TextSpan(
                  text: 'I have read and agree to the',
                  style: GoogleFonts.poppins(
                      color: Color(0xff000000),
                      fontSize: 15,
                      letterSpacing: 0.4,
                    ),
                ),
                TextSpan(
                  text: ' Terms & Conditions ',
                  style: GoogleFonts.poppins(
                      color: Colors.blue,
                      fontSize: 15,
                      letterSpacing: 0.4,
                    ),
                    recognizer: TapGestureRecognizer()
                    ..onTap = () {
                      launchUrl(Uri.parse('https://toy-zania.com/pages/term') );
                    }                      
                ),
                TextSpan(
                  text: '& Warranty.',
                  style: GoogleFonts.poppins(
                      color: Color(0xff000000),
                      fontSize: 15,
                      letterSpacing: 0.4,
                    ),
                ),
              ]),
                  ),
                  
                  value: _isChecked1,
                  onChanged: (bool? newValue) {
                    setState(() {
                      _isChecked1 = newValue ?? false;
                    });
                  },
                  activeColor: Color(0xff82b235),
                  controlAffinity: ListTileControlAffinity.leading,
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(top: 40),
                child: SizedBox(
                  width: 320, // <-- match_parent
                  height: 45,
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                      foregroundColor: Color(0xffe5e5e5),
                      backgroundColor: Color(0xff734FE0),
                    ),
                    onPressed: () {
                      createAccount();
                    },
                    child: Text('CREATE ACCOUNT',
                        style: GoogleFonts.poppins(
                          fontSize: 16,
                          letterSpacing: 1,
                        )),
                  ),
                ),
              ),

Solution

  • You can listen to the TextEditingControllers and others button/objects that will be responsible to control the button state. Here is an example

    class MyApp extends StatefulWidget {
      const MyApp({super.key});
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      final TextEditingController _controller = TextEditingController();
      final TextEditingController _controller2 = TextEditingController();
      bool isCheck = false;
    
      bool enableButton = false;
    
      void _checkFields() {
        enableButton =
            _controller.text.isNotEmpty && _controller2.text.isNotEmpty && isCheck;
        setState(() {});
      }
    
      @override
      void initState() {
        super.initState();
        _controller.addListener(_checkFields);
        _controller2.addListener(_checkFields);
      }
      //dispose them
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextField(
                  controller: _controller,
                ),
                TextField(
                  controller: _controller2,
                ),
                Checkbox(
                    value: isCheck,
                    onChanged: (value) {
                      setState(() {
                        isCheck = value ?? false;
                      });
                      _checkFields();
                    }),
                ElevatedButton(
                  onPressed: enableButton ? () {} : null,
                  child: const Text('Submit'),
                ),
              ],
            ),
          ),
        );
      }
    }