How to pass a function as a validator in a TextFormField?

5,190

Perhaps the function return type should be String? so that it fits the validator prototype!

  Widget Field(String changedValue, String label, bool isTextObscured) {
    return TextFormField(
      decoration: InputDecoration(labelText: label),
      validator: checkFieldEmpty,
    );
  }

 String? checkFieldEmpty(String? fieldContent) { //<-- add String? as a return type
    if(fieldContent.isEmpty) {
      return 'Ce champ est obligatoire.';
    }
    return null;
  }

A more appropriate way of doing this in Flutter

Remember, flutter is a declarative language. That is, you build your app by composing a widget tree. Here, you are using a function to return a Widget. That is breaking this rule. Instead, you should declare your own custom widget that implements the TextField Widget. Here's how:

1. Declare your custom widget

// Declare your CustomTextField as a Stateless/Stateful Widget
class MyCustomTextField extends StatelessWidget {
  // Declare your custom vars, including your validator function
  final String? changedValue; 
  final String? label; 
  final bool? isTextObscured;
  final String? Function(String?)? validator;

  const MyCustomTextField({
    Key? key, 
    this.changedValue, 
    this.label,
    this.isTextObscured,
    this.validator,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: InputDecoration(labelText: label),
      validator: validator,
    );
  }
}

2. Use your custom widget

Now you can use this custom widget as a child of any other widget:

class ParentWidget extends StatelessWidget {
  const ParentWidget({Key? key}) : super(key: key);

  // This is your custom validator function and can leave
  // anywhere ;)
  Stirng? customValidtaor(String? fieldContent) => fieldContent.isEmpty? 'Ce champ est obligatoire.': null

  @override
  Widget build(BuildContext context) {
    return MyCustomTextField(
      label: 'Some label'
      // declare the validator here...
      // valiator: (fieldContent) => fieldContent.isEmpty? 'Ce champ est obligatoire.': null
      // or use your custom validator function
      validator: customValidator,
    );
  }
}

By doing this, you are respecting Flutter's best practices by using Widget composition ;)

Share:
5,190
gabhar
Author by

gabhar

Updated on December 30, 2022

Comments

  • gabhar
    gabhar over 1 year

    I'm wondering if I can pass a function as a validator. I tried, but got no results.

      Widget Field(String changedValue, String label, bool isTextObscured) {
        return TextFormField(
          decoration: InputDecoration(labelText: label),
          validator: checkFieldEmpty,
        );
      }
    
      checkFieldEmpty(String fieldContent) {
        if(fieldContent.isEmpty) {
          return 'Ce champ est obligatoire.';
        }
        return null;
      }
    
    • Stewie Griffin
      Stewie Griffin almost 3 years
      Yes, you can, but fieldContent must be nullable. Replace String with String?. Also, make the return type of your checkFieldEmpty function String? as is said in the answers below.
  • gabhar
    gabhar almost 3 years
    I'm afraid it still doesn't work... "The argument type 'String? Function(String)' can't be assigned to the parameter type 'String? Function(String?)?'."
  • Younss AIT MOU
    Younss AIT MOU almost 3 years
    yup just update the function:String? function(String? fieldContent){/*...*/} sorry I missed the argument type. I have updated my response accordingly ;)
  • oleksa
    oleksa almost 2 years
    validator method signature should have String? parameter and return types. Like String? checkFieldEmpty(String? v)