Building Custom Form Fields in Flutter: Creating Validation Behaviors for Any Widget

Odeh Sebastine
Stackademic
Published in
5 min readJul 11, 2023

--

As the range of input fields in apps increases, dependent on the UI specifications of the project, the need for a uniform validation process for all input becomes even more paramount. Luckily, flutter allows any widget to obey form validation rules exactly like text form fields. In this article, we will be doing just that by making custom form fields of custom widgets.

To follow along as we learn to make custom form fields, it’s recommended to fulfil these prerequisites:

  • Some flutter knowledge.
  • Flutter SDK is installed.
  • Burning passion to learn something new.

To kick the article off, we’ll be building two custom widgets. The first widget would be a custom image picker and the second would be a group of radio buttons both with form validation.

To start this project we go through the following steps

  • We create a new flutter project which we’re going to call form_widget_demo.
  • Next, we add the image picker package to our pubspec.yaml, we won’t be covering setting it up as it’s outside the scope of this article but you can go through the readme here before continuing.

Here’s how our pubspec.yaml dependencies list looks after adding the image_picker package

project’s pubspec.yaml file

And our main.dart looks like this

project’s main.dart

Now we are going to create the base image picker widget which we’ll extend to being a form field shortly. We start by creating an image_picker_field.dart file and filling it with the following code:

Image picker widget that opens the device’s gallery to select an image.

Then we add this widget to the column in our MyHomePage widget in our main.dart. Also, we’ll be wrapping the column with a Form to apply form validation and also a button to validate the custom form fields we’ll be creating. Our MyHomePage widget would look like this

Running the app on your device you should see similar as displayed below

Pressing the validate form button doesn’t catch any validation error, in this case not selecting an image, and shows the form “is valid” snack bar, we will be fixing that next.

Our image picker widget validation would work in a way that takes inspiration from text form fields, we’ll give the sides a red border with the validation error message at the bottom also in red. Also taking inspiration from text form fields, we’ll introduce an image picker input controller. The image_picker_field.dart file is updated as shown below

We’ve updated the ImagePickerField widget to take 3 parameters, a controller, an onChanged and a side. The controller is a nullable ImagePickerInputController which is defined at the bottom of the file as a class that extends ValueNotifier and it takes a type File. We also provide fileName getter which we use to get the file’s name and a file setter to update the value and notify its listeners. We use an onChanged to emit the values from the controller as they’re updated and then a side which we override in the ImagePickerFormField to show the red-coloured border.

The ImagePickerFormField extends FormField which allows generic types and allows a parent form widget to control its form behaviour like textformFields. We also provide a controller, onChanged as before with a super.validator, super.autovalidateMode, which allows us to pass validation rules. We override the builder parameter of the extended widget class which is a callback that provides a FormFieldState that exposes getters such as errorText for getting validation error text and hasError, a boolean to check if there’s an error. We also update the ImagePickerField to ImagePickerFormField in our main.dart and then add a validation rule to the validator callback which is shown below

This is all we need to make an image picker field a form field which obeys the parent form’s key validation and auto-validation behaviour.

Next, we’ll be working on making a popular existing use case operate as a form field, that is a group of radio options.

We’ll start by creating a file we’ll name radio_button_group.dart and add the following code to it

Base radio options group widget

Updating our MyHomePage column with a sized box for space and the RadioButtonGroup, our UI and code look as below

Updated UI with Radio button group
Updated column code

Now for how we want validation errors to be displayed, going with the same idea as before we will show the validator error message at the bottom of the group and this time we’ll make the radios red to show there’s an error by updating the radio’s fill color property. Our updated radio_button_group.dart is shown as follows

Updated radio button group with form field validation in place

Keeping to the same conventions as before we have a controller, onChanged and this time fillColor as parameters of the RadioButtonGroup widget. We also have a form widget that follows what we did earlier with the ImagePickerWidget. Our updated MyHomePage widget looks as follows

Updated MyHomePage column with the RadioButtonFormGroup widget with validation

Different UI for each validation state looks as follows

In conclusion, we’ve learnt how to turn custom widgets to form fields. While this works, it could be better implemented. The implementation of form validation in Flutter’s text field requires some additional overrides which you can check from the source code found here. The full project and demo are also available on GitHub.

If you have any questions or comments about this article, please do not hesitate to contact me on Twitter at H3ndrick_, on LinkedIn at Sebastine Odeh or on Github CoderNamedHendrick.

Stackademic 🎓

Thank you for reading until the end. Before you go:

--

--

Software engineer with a knack for mobile, building apps with Flutter. Follow me to join my development journey.