Home > Software design >  Flutter - Reusable Widget TextFormField - validation does not work
Flutter - Reusable Widget TextFormField - validation does not work

Time:09-28

I am using a reusable widget and trying to pass a validation before the form is submitted. But, I am not getting the error message that I should get. I have read the code several times, but do not find where is the problem. If you can have a quick look and tell me what I am missing it would be great.

import 'package:flutter/material.dart';

class TextFormFieldWidget extends StatefulWidget {

  String hintText;
  TextEditingController controller;
  int maxLength;
  int maxLines;
 // Function onChanged;
  TextInputAction? actionKeyboard;
  String? parametersValidate;
  String? defaultText;
  String? labelText;
  TextInputType? textInputType;
  FocusNode? focusNode;
  bool? obscureText;
  Widget? prefixIcon;
  Function onSubmitField;
  Function? onFieldTap;
  Function? functionValidate;
  String? decoration;
  String? validator;
  //final dynamic Function(String?)? onChanged;


  TextFormFieldWidget({
    Key? key,
    required this.hintText,
    required this.controller,
    required this.onSubmitField,
    required this.maxLength,
    required this.maxLines,
  //  required this.onChanged,
    this.labelText,
    this.validator,
    this.parametersValidate,
    this.textInputType,
    this.onFieldTap,
    this.defaultText,
    this.actionKeyboard,
    this.prefixIcon,
    this.focusNode,
    this.obscureText,
    this.functionValidate,
    this.decoration,
  }) : super(key: key);

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

class _TextFormFieldWidgetState extends State<TextFormFieldWidget> {
  double bottomPaddingToError = 12;

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: Theme.of(context).copyWith(
        primaryColor: Colors.black,
      ),
      child: TextFormField(
        cursorColor: Colors.black,
       // obscureText: widget.obscureText,
        keyboardType: widget.textInputType,
        textInputAction: widget.actionKeyboard,
        focusNode: widget.focusNode,
        maxLength: widget.maxLength,
        maxLines: widget.maxLines,

        style: const TextStyle(
          color: Colors.black,
          fontSize: 16.0,
          fontWeight: FontWeight.w200,
          fontStyle: FontStyle.normal,
          letterSpacing: 1.2,
        ),
        initialValue: widget.defaultText,
        decoration: InputDecoration(
          prefixIcon: widget.prefixIcon,
          hintText: widget.hintText,
        //  labelText: widget.decoration!,

         // enabledBorder: const OutlineInputBorder(
         //   borderSide: BorderSide(color: Colors.black),
         // ),
        //  focusedBorder: const OutlineInputBorder(
        //    borderSide: BorderSide(color: Colors.black),
        //  ),
          hintStyle: const TextStyle(
            color: Colors.grey,
            fontSize: 14.0,
            fontWeight: FontWeight.w300,
            fontStyle: FontStyle.normal,
            letterSpacing: 1.2,
          ),
          contentPadding: EdgeInsets.only(
              top: 12, bottom: bottomPaddingToError, left: 8.0, right: 8.0),
          isDense: true,
          errorStyle: const TextStyle(
            color: Colors.red,
            fontSize: 12.0,
            fontWeight: FontWeight.w300,
            fontStyle: FontStyle.normal,
            letterSpacing: 1.2,
          ),
          errorBorder: const OutlineInputBorder(
            borderSide: BorderSide(color: Colors.black),
          ),
          focusedErrorBorder: const OutlineInputBorder(
            borderSide: BorderSide(color: Colors.black),
          ),
        ),
        controller: widget.controller,
        validator: (value) {
          if (widget.functionValidate != null) {
            String resultValidate =
            widget.functionValidate!(value, widget.parametersValidate);
            if (resultValidate != null) {
              return resultValidate;
            }
          }
          return null;
        },
        onFieldSubmitted: (value) {
          if (widget.onSubmitField != null) widget.onSubmitField();
        },
        onTap: () {
          if (widget.onFieldTap != null) widget.onFieldTap!();
        },


      ),
    );
  }
}

String? commonValidation(String value, String messageError) {
  var required = requiredValidator(value, messageError);
  if (required != null) {
    return required;
  }
  return null;
}

String? requiredValidator(value, messageError) {
  if (value.isEmpty) {
    return messageError;
  }
  return null;
}

void changeFocus(
    BuildContext context, FocusNode currentFocus, FocusNode nextFocus) {
  currentFocus.unfocus();
  FocusScope.of(context).requestFocus(nextFocus);
}

Widget

Widget _buildTextFormField(String myHintText,TextEditingController myController,
      int length,int lines,String myContent) {
    return TextFormFieldWidget(
      hintText: myHintText,
      decoration: 'Test 33',
      controller: myController,
      maxLength: length,
      maxLines: lines,
      onSubmitField: () {},
      validator:checkFieldEmpty( myContent),
    );

String? checkFieldEmpty(String? fieldContent) { //<-- add String? as a return type
    if(fieldContent!.isEmpty) {
      return 'Field empty => Please, change this.';
    }
    return null;

View

SingleChildScrollView(
        child: Form(
          key: _addFirstTaskFormKey,
          child: Column(
            children: [
              _buildTextFormField('Task Name',taskNameController,100,3,taskNameController.text),
ElevatedButton(
                onPressed: (){

                  if(_addFirstTaskFormKey.currentState!.validate()){
                    print ('validated');
                    //taskItems.taskName = taskNameController.text;
                    //taskItems.notes = notesController.text;
                  }
                }, child: const Text('Press'),
              ),

CodePudding user response:

I think you're relatively new to flutter, don't worry I got you, FormValidators are used to validate multiple fields declared inside a Form Widget. Form widget uses a global Form key declared Like this,

final _formKey = GlobalKey<FormState>();

and fields Like this,

   child: Form(child:Column(children:[
TextFormField(controller:controller),
TextFormField(controller:controller),
],),),

so when you need to validate fields just call,

_formKey.validate();

in the case above you are making a CustomTextFormField

you don't necessarily need to make it a stateful widget, use StateLess Widget instead,

class CustomTextFormField extends StateLessWidget {
  final TextInputType? keyboardType;
  final TextEditingController? controller;
  final FormFieldValidator<String>? validator;
  final ValueChanged<String?>? onSaved;
  final Function(String)? onChanged;
  final VoidCallback? onTap;
  const CustomTextFormField(
  this.keyboardType, 
  this.controller,
  this.validator,
  this.onSaved,
  this.onChanged,
  this.onTap,
  );
   @override
  Widget build(BuildContext context) {
    return TextFormField(
        keyboardType: keyboardType,
        validator: validator,
        autovalidateMode: autoValidateMode,    
        onSaved: onSaved,
        onChanged: onChanged,
);
}

and use it like this

    CustomTextFormField(
    validator: (String? val) {
    if(val==null) {
    return "Value cannot be empty";
   }
    return null;
   },
  ),

add any other validation that you may want to apply and on save button call

if(_formKey.currentState.validate()) {
  //SaveData
}else {
print("Validation Error")
}

CodePudding user response:

This may be the problem. You're using null values. Flutter has Sound null safety so this means you can't set variables to null. I'm really curious, does your code even run?

Solution: Scrap your validator and read through the Flutter Docs. They'll walk you through building a Form with validation here

 validator: (value) {
          if (widget.functionValidate != null) {
            String resultValidate =
            widget.functionValidate!(value, widget.parametersValidate);
            if (resultValidate != null) {
              return resultValidate;
            }
          }
          return null;
        },
        onFieldSubmitted: (value) {
          if (widget.onSubmitField != null) widget.onSubmitField();
        },
        onTap: () {
          if (widget.onFieldTap != null) widget.onFieldTap!();
        },


      ),
    );
  }
  • Related