Home > database >  Flutter TextFormField Validator show error suffixIcon on text empty or null
Flutter TextFormField Validator show error suffixIcon on text empty or null

Time:02-11

I am having a flutter TextFormField and i am already showing an error and outlined border color change to red when text is empty or null. What i want is to also show a suffixIcon when TextFormField is empty

below is my code


class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

  @override
  _LoginState createState() => _LoginState();
}

class _LoginState extends State<Login> {
  final loginFormKey = GlobalKey<FormState>();

  TextEditingController userNameController = TextEditingController();

  FocusNode userNameFocusNode = FocusNode();

  bool userNameHasFocus = false;

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

  @override
  void dispose() {
    super.dispose();
    userNameController.dispose();
    userNameFocusNode.dispose();
  
  }

  @override
  Widget build(BuildContext context) {
  
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
          child: Center(
              child: Form(
                  autovalidateMode: AutovalidateMode.onUserInteraction,
                  key: loginFormKey,
                  child: Column(
                    children: [
                      Container(
                          padding: const EdgeInsets.all(1),
                          margin: const EdgeInsets.only(top: 5, bottom: 5),
                          child: const Text(
                            "Welcome to my app",
                            textAlign: TextAlign.center,
                          )),
                      Container(
                          margin: const EdgeInsets.only(
                              top: 1, bottom: 2, right: 1, left: 10),
                          child: TextFormField(
                            focusNode: userNameFocusNode,
                            controller: userNameController,
                            decoration: InputDecoration(
                              labelText: "Please Enter Username",
                              border: OutlineInputBorder(),
                            ),
                            validator: (phoneNo) {
                              if (phoneNo!.isEmpty) {
                                userNameFocusNode.requestFocus();
                                userNameHasFocus = true;
                                return "You must enter username";
                              } else {
                                userNameHasFocus = false;
                                return null;
                              }
                            },
                          )),
                      Container(
                          margin: const EdgeInsets.only(
                              top: 2, bottom: 1, right: 10, left: 10),
                          child: ElevatedButton(
                              onPressed: () {

                                if (loginFormKey.currentState!.validate()) {

                                  print(proceed)

                                }

                              },
                              child: Text("Login"),
                              style: ElevatedButton.styleFrom(
                                shape: StadiumBorder(),
                              )))
                    ],
                  )))),
    );
  }
}

The part that i am interested is below in validator


validator: (phoneNo) {
                              if (phoneNo!.isEmpty) {
                                userNameFocusNode.requestFocus();
                                userNameHasFocus = true;
                                return "You must enter username";
                              } else {
                                userNameHasFocus = false;
                                return null;
                              }
                            },

Where if phoneNo!.isEmpty i should show something like this below


 suffixIcon: Icon(Icons.error_outline_rounded, color: Colors.red)

CodePudding user response:

You can use a bool to show the suffixIcon.

  bool showSuffix = false;
  
  @override
  void initState() {
    super.initState();
    userNameController.addListener(() {
      if (userNameController.text.isEmpty) {
        showSuffix = true;
      } else {
        showSuffix = false;
      }
      setState(() {});
    });
  }

 ///.........

 /// aslo can be used [Visibility] widget
 suffixIcon: showSuffix
    ? const Icon(Icons.error_outline_rounded,
        color: Colors.red)
    : null,

CodePudding user response:

You need to show the icon or hide it according to a condition if the TextFormField is validated or not.

Remove autovalidateMode: AutovalidateMode.onUserInteraction and add onChanged method instead like this:

import 'package:flutter/material.dart';

class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

  @override
  _LoginState createState() => _LoginState();
}

class _LoginState extends State<Login> {
  final loginFormKey = GlobalKey<FormState>();

  TextEditingController userNameController = TextEditingController();

  FocusNode userNameFocusNode = FocusNode();

  bool userNameHasFocus = false;
  bool validated = true;

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

  @override
  void dispose() {
    super.dispose();
    userNameController.dispose();
    userNameFocusNode.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Center(
          child: Form(
            key: loginFormKey,
            child: Column(
              children: [
                Container(
                    padding: const EdgeInsets.all(1),
                    margin: const EdgeInsets.only(top: 5, bottom: 5),
                    child: const Text(
                      "Welcome to my app",
                      textAlign: TextAlign.center,
                    )),
                Container(
                    margin: const EdgeInsets.only(top: 1, bottom: 2, right: 1, left: 10),
                    child: TextFormField(
                      focusNode: userNameFocusNode,
                      controller: userNameController,
                      decoration: InputDecoration(
                          labelText: "Please Enter Username",
                          border: const OutlineInputBorder(),
                          suffixIcon: !validated ? const Icon(Icons.error_outline_rounded, color: Colors.red) : const SizedBox()),
                      validator: (phoneNo) {
                        if (phoneNo!.isEmpty) {
                          userNameFocusNode.requestFocus();
                          userNameHasFocus = true;
                          return "You must enter username";
                        } else {
                          userNameHasFocus = false;
                          return null;
                        }
                      },
                      onChanged: (value) {
                        if (value.isNotEmpty) {
                          setState(() {
                            validated = true;
                            loginFormKey.currentState!.validate();
                          });
                        }
                      },
                    )),
                Container(
                  margin: const EdgeInsets.only(top: 2, bottom: 1, right: 10, left: 10),
                  child: ElevatedButton(
                    onPressed: () {
                      if (loginFormKey.currentState!.validate()) {
                        setState(() {
                          validated = loginFormKey.currentState!.validate();
                        });
                      } else {
                        setState(() {
                          validated = loginFormKey.currentState!.validate();
                        });
                      }
                    },
                    child: const Text("Login"),
                    style: ElevatedButton.styleFrom(
                      shape: const StadiumBorder(),
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Happy coding!!

  • Related