how to create resuable textfield with validator in flutter

1,775

Solution 1

I have been using TextFormField in a reusable way like this , it has served me for all the purposes i needed , i think it works for your case too

class BoxTextField extends StatelessWidget {
  final TextEditingController controller;
  final FormFieldValidator<String> validator;
  final bool obsecure;
  final bool readOnly;
  final VoidCallback onTap;
  final VoidCallback onEditingCompleted;
  final TextInputType keyboardType;
  final ValueChanged<String> onChanged;
  final bool isMulti;
  final bool autofocus;
  final bool enabled;
  final String errorText;
  final String label;
  final Widget suffix;
  final Widget prefix;

  BoxTextField(
      {Key key,
      this.controller,
      this.validator,
      this.keyboardType = TextInputType.text,
      this.obsecure = false,
      this.onTap,
      this.isMulti = false,
      this.readOnly = false,
      this.autofocus = false,
      this.errorText,
      @required this.label,
      this.suffix,
      this.prefix,
      this.enabled = true,
      this.onEditingCompleted,
      this.onChanged})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 4),
      child: TextFormField(
          onChanged: onChanged,
          onEditingComplete: onEditingCompleted,
          autofocus: autofocus,
          minLines: isMulti ? 4 : 1,
          maxLines: isMulti ? null : 1,
          onTap: onTap,
          enabled: enabled,
          readOnly: readOnly,
          obscureText: obsecure,
          keyboardType: keyboardType,
          controller: controller,
          decoration: InputDecoration(
            errorText: errorText,
            prefixIcon: prefix,
            suffixIcon: suffix,
            labelStyle: TextStyle(fontSize: lableFontSize()),
            labelText: label,
            hintStyle: TextStyle(color: Colors.blueGrey, fontSize: 15),
            contentPadding: EdgeInsets.symmetric(vertical: 8, horizontal: 20),
            enabledBorder: textFieldfocused(),
            border: textFieldfocused(),
            focusedBorder: textFieldfocused(),
            errorBorder: errorrTextFieldBorder(),
            focusedErrorBorder: errorrTextFieldBorder(),
          ),
          validator: validator),
    );
  }
}

This is the Usage

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  TextEditingController _emailPhone = new TextEditingController();
  TextEditingController _password = new TextEditingController();

  GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

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

  String loginError;
  bool loggingIn = false;

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverList(
            delegate: SliverChildListDelegate([
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20.0),
            child: Form(
                key: _formKey,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    SizedBox(
                      height: 50,
                    ),
                    BoxTextField(
                      validator: (str) {
                        if (str.isEmpty) {
                          return tr('common.required');
                        }

                        return null;
                      },
                      controller: _emailPhone,
                      label: tr('login.username'),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    BoxTextField(
                      label: tr('login.password'),
                      controller: _password,
                      obsecure: true,
                      validator: (str) {
                        if (str.isEmpty) {
                          return tr('common.required');
                        }

                        return null;
                      },
                    ),
         Center(
                        child: BoxButton(
                      loading: loggingIn,
                      lable: tr('login.btn'),
                      onPressed: () {
                          
                            },
                    )),
                  ],
                )),
          )
        ]))
      ],
    );
  }
}

Solution 2

Replace your code and try this:

RoundedInputField(
              hintText: "Username",
              icon: Icons.email,
              fontsize: 20,
              controller: TextEditingController(text: user.username),
              onChanged: (value) {
                user.username = value;
              },
              validate: (value) {
                if (value.isEmpty) {
                  return "This field is required";
                }
                return null;
              },
            ),
Share:
1,775
TimeToCode
Author by

TimeToCode

I'm a motivated programmer, can do anything with passion. Currently working on flutter.

Updated on December 20, 2022

Comments

  • TimeToCode
    TimeToCode over 1 year

    I am creating a login form which has username and password field, i want to add validation when user skip any field. I have created this reusable textfield.

    class RoundedInputField extends StatelessWidget {
      final String hintText;
      final ValueChanged<String> onChanged;
      final TextEditingController controller;
      final FormFieldValidator validate;
      const RoundedInputField({Key key, this.hintText,
        this.onChanged,
       this.controller,this.validate,
     
      })
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return TextFieldContainer(
          child: TextFormField(
            onChanged: onChanged,            
            controller: TextEditingController(),
            validator: validate,
            decoration: InputDecoration(
              hintText: hintText,
              border: InputBorder.none,
            ),
          ),
        );
      }
    }
    
    

    and calling it like this

     RoundedInputField(hintText: "Username",icon: Icons.email,fontsize: 20,
                    controller: TextEditingController(text: user.username),
                    onChanged: (value){
                      user.username=value;
                    },
                    validate: (value){
                      if(value.isEmpty){
                        return "This field is required";
                      }
                    },
                    ),
    

    but validator property is not working properly, here it is.

    enter image description here

    please help if anyone know how to fix it!