Forms in Flutter without hassle!

Overview

Super Form

pub package Tests status style: lint codecov

Quick, familiar and extensible forms in Flutter πŸ’ͺ
No magical configuration required πŸŽ‰

Managing form state with standard Flutter forms can be extremely tedious. Super Form manages form values, errors and additional properties like whether an input was touched without complicated logic. Super Form also provides a set of ready to use form widgets, but don't worry it is also extremely simple to implement your own.

Does it use state management?

Super Form follows the idea of form state being inherently ephemeral and local, so tracking it in Redux or Bloc is unnecessary. Super Form is also faster since changing one field doesn't trigger an update to all fields. While this behavior can be achieved with Redux/Bloc it is not done by default.

Having said that it is possible to save the values to anything you want.

Usage

  1. Create SuperForm widget at the top of your form the as you would do with Form. You may want to add a GlobalKey, but that's not required.
SuperForm(
  validationMode: ValidationMode.onBlur,
  onSubmit: (values) {
    // Do your thing
    print(values.toString());
  },
  child: Column(...)
)
  1. Create fields
TextSuperFormField(
  decoration: const InputDecoration(labelText: "Email"),
  name: "email",
  rules: [RequiredRule("Must not be empty")],
),
  1. Add a button or whatever you want to submit the form
OutlinedButton(
  onPressed: () => SuperForm.of(context, listen: false).submit(),
  child: const Text("Sign in"),
),

Note that you may want to wrap the child (like example of submit button) of the SuperForm in Builder to be able to get SuperForm instance in the same widget.

Validation

SuperForm comes with a set of validation rules. These are relatively simple synchronous validators. Each validator takes error message as an parameter which will be automatically displayed when the value won't pass the validation. This means you can compose these rules and show super helpful error messages.

Note that the order of the rules matters. Validation takes place from the beginning of the list.

TextSuperFormField(
  decoration: const InputDecoration(labelText: "Password"),
  name: "password",
  rules: [
    RequiredRule("Must not be empty"),
    MinimumLengthRule(
      6,
      "Must be at least 6 characters",
    ),
    CustomRule((value) {
      double strength = estimatePasswordStrength(value);

      if (strength < 0.3) return "Password is too weak";
    })
  ],
),

To create your own rules you can either extend SuperFormFieldRule, existing rule or use CustomRule, which takes a function as its parameter.

Validation modes

Validation is always run when the form is submitted, after that invalid fields will re-validate on change. However you can customize the initial behavior by passing validationMode to SuperForm widget.

  • onSubmit (default) - validation will trigger only on submit
  • onBlur - validation will also trigger when field loses focus
  • onChange - validation will trigger when the field value is changed

Virtual fields

There are cases where you want to have field in the form, but have no actual controls for it. Super form can do it! You just need to register the field. You can do it easily in onInit callback of the SuperForm widget.

SuperForm(
  onInit: (form) {
    form.register(
      name: "termsAndConditionsAccepted",
      rules: [IsEqualRule(true, 'You need to accept terms and conditions')],
    );
  },
  // ...
)

After you register a field you can trigger all standard operations like setting value, marking it as touched or triggering a validation. Submitting the form will also validate this field.

Interacting programmatically

SuperForm makes it super easy to interact, like setting a value, programmatically. Just retrieve SuperForm instance from context and you can do magic. Just remember that the field must be registered.

A perfect example is where you want to use showDatePicker as a way to collect form data:

showDatePicker(
  context: context,
  initialDate: DateTime.now(),
  firstDate: DateTime.now(),
  lastDate: DateTime.utc(2040),
).then((value) {
  SuperForm.of(context, listen: false).setValue("to", value);
});

Errors

Normally you don't have to worry about displaying errors as fields are doing that automatically. However there are cases where you don't have a widget for a field, but you want to display any possible errors. That's where SuperFormErrorText comes to help. It displays single error message, with a errorColor from Theme, when there is one.

SuperFormErrorText(name: "termsAndConditionsAccepted")

Initial values

Providing initial values for your fields is extremely easy. Just provide a map of field name and its initial value to SuperForm widget. Changing this property does not affect form immediately - new initial values will be used after field is reset - can be done via reset method on SuperFormState.

SuperForm(
  initialValues: const {"quantity": 1},
  onSubmit: (values) {
    // Do your thing
    print(values.toString());
  },
  child: // ...
);

Why use dynamic?

While it comes with many implications it allows to put everything into one place. Having tried to do that using generics resulted in putting lots of stupid mapping functions or additional classes. Code generation could solve that, but then I would name this package SuperChonkyForm. In the end, when static metaprogramming shows up I'll probably create SuperForm v2 which would preserve types.

Contributing

Feel free to create issues, fix bugs, add new functionalities even if you are not sure about. Everyone is welcome!

Comments
  • Change the submit value in the property field?

    Change the submit value in the property field?

    hi, can i change the submit value in the property field?. example:;

    onSubmitValue:(value){
    return value.removeChar(',');
    }
    

    in superFormField im adding Money inputFormatters, and the value has Char "," in '99,999.00'. can i change this to '99999.99'. thanks and I'm new to flutter. This SuperForm is a great library for me.

    opened by hendrisoni 2
  • Fix analyzer issues after Flutter upgrade

    Fix analyzer issues after Flutter upgrade

    Description

    Let's improve the pub score to 130

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [x] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Refactor/rules handling

    Refactor/rules handling

    Description

    The problem with rules is that it is impossible to figure out if rules have actually been changed between builds and because rules have been a part of field data it was considered as a change for that field.

    This allowed to easily get into an infinite rendering loop.

    This PR will separate field rules from field data, thus providing the ability to prevent unnecessary build triggers and ignore rules changes since those are not actually needed for rendering and are not really a part of the state either.

    Updating rules by programmatically on SuperForm instance never made much sense for fields that have their widgets so there is no need to implement listening on that. If there would be a need for that it would probably be exposed via onRulesChange callback similar to onChange

    Consider this bug fix as a minor breaking change.

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [x] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [x] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [x] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [x] πŸ—‘οΈ Chore
    bug 
    opened by pr0gramista 1
  • Add ability to disable whole form.

    Add ability to disable whole form.

    Add modified getter to form state. Fix issue where form would update dependents too often when changing form property.

    Description

    This allows to easily lock all the fields. Can be useful when waiting for data from API as shown in the Survey demo.

    Type of Change

    • [x] ✨ New feature (non-breaking change which adds functionality)
    • [x] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Add additional tests for almost 100% code coverage

    Add additional tests for almost 100% code coverage

    Description

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Remove abandoned SuperFormFieldData.of

    Remove abandoned SuperFormFieldData.of

    Description

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [x] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Fix validation error to actually not extend Dart's Error class

    Fix validation error to actually not extend Dart's Error class

    Description

    It was a mistake to use Dart "Error" as a base class. It isn't meant to be used like that. Exception would be better but I don't think it is good.

    I was thinking about renaming the ValidationError to ValidationFailure since this is actually more meaningful - the validation did well, but the result is a failure. One argument against that is that most people (or at least I think so) are familiar with errors.

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [x] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Set field as touched when it loses focus

    Set field as touched when it loses focus

    Description

    Made field set themselves as touched after they lose focus. This isn't really common, especially on mobile devices, but could be useful for desktop environments.

    Also removed assertions from TextSuperFormField. It is extremely stupid having to check these every Flutter release and they don't provide any real benefits. Added test for un-registering field that is still active.

    Type of Change

    • [x] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Add option to disable super form fields

    Add option to disable super form fields

    Description

    Normally field are disabled by not providing the main value callback that is onChanged/onSelected so on. However SuperForm fields have been adding this callback all the time which prevented users from disabling the form fields. This PR adds enabled (similar to TextField) field which adds additional contol.

    Type of Change

    • [x] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • State restoration

    State restoration

    Description

    Basic support for state restoration. Currently supports only collections and primitives.

    Also fixes deprecated accentColor in Theme and prevents running same GitHub action checks twice.

    Type of Change

    • [x] ✨ New feature (non-breaking change which adds functionality)
    • [x] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [x] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by pr0gramista 1
  • Feature/debug to string properties

    Feature/debug to string properties

    Description

    Introduces debugProperties and toString on rules. Just helps with overall debugging.

    These were meant to be merged earlier, but I wasn't sure how to test it.

    Type of Change

    • [x] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    enhancement 
    opened by pr0gramista 1
  • Should Checkbox use Set as underlying value?

    Should Checkbox use Set as underlying value?

    Lists are in general much more common and in theory a little bit faster for iteration (Checkbox builder). Sets are more suitable for the overall domain since values can't be duplicated. It is also better for comparision since order doesn't matter anymore and at this moment checkboxes are doing that as user interact.

    This would break compatibility.

    It might be also a good idea to make Checkbox accept both Set and List as initial value.

    enhancement 
    opened by pr0gramista 0
Owner
Bartosz WiΕ›niewski
Everything* Developer, Google Tech enthusiast, Co-organizer of WrocΕ‚awJUG, πŸ›  DIY lover, content creator and 🍺 homebrewer
Bartosz WiΕ›niewski
Sample Flutter app for creating basic login forms validation for email and passwords

Email validation Flutter example Sample flutter app showing how to validate a e-mail login form. This example uses the email_validator package for val

Fredrik Eilertsen 22 Dec 15, 2022
Jannis 0 Jan 29, 2022
Simple tool to open WhatsApp chat without saving the number, developed using Google's Flutter Framework. for Android/ IOS/ Desktop/ Web

OpenWp Simple tool to open WhatsApp chat without saving the number Explore the docs Β» View Demo Β· Report Bug Β· Request Feature Table of Contents About

Swarup Bhanja Chowdhury 15 Nov 1, 2022
Android App written with Flutter/Dart to navigate medium.com without limitations.

Medium Unlimited An Android application written with Flutter/Dart to read medium.com without limitations. Features Read medium without reading limits

null 29 Dec 22, 2022
Multi-language support in Flutter without using any third-party library

flutter_localization_app A new Flutter application. Getting Started This project is a starting point for a Flutter application. A few resources to get

Gulshan Yadav 1 Oct 30, 2021
A Flutter plugin that provides assets abstraction management APIs without UI integration, you can get assets (image/video/audio) on Android, iOS and macOS.

photo_manager Photo/Assets management APIs for Flutter without UI integration, you can get assets (image/video/audio) from Android, iOS and macOS. 提供相

FlutterCandies 526 Jan 4, 2023
"FlutterMoneyFormatter" is a Flutter extension to formatting various types of currencies according to the characteristics you like, without having to be tied to any localization.

FlutterMoneyFormatter FlutterMoneyFormatter is a Flutter extension to formatting various types of currencies according to the characteristics you like

Fadhly Permata 81 Jan 1, 2023
A flutter plugin to play Youtube Videos without API Key in range of Quality(144p, 240p,360p,480p,720p and 1080p).

Youtube Player Plugin This plugin is discontinued. Please use youtube_player_flutter which is an officially provided way of playing youtube videos, su

Sarbagya Dhaubanjar 120 Nov 13, 2022
Easy nav - A simple wrapper around flutter navigator, dialogs and snackbar to do those things without context

EasyNav Just a simple wrapper around flutter navigator, dialogs and snackbar to

Abdul Shakoor 2 Feb 26, 2022
Win32 runner - Run a Flutter app without needing a lick of C/C++ code. Just Dart

Experimental package for running Flutter apps from a Dart runner, instead of the

Tim Sneath 51 Sep 25, 2022
A test driver for Flutter to do QA testing without sharing app source code.

Autopilot A test driver for Flutter to do QA testing without sharing app source code. It exposes a JSON API using an HTTP server running inside the ap

Ajin Asokan 70 Dec 30, 2022
A Flutter mobile application built completely using DhiWise and Supabase without coding single line of code. With 100% system generated code

Flutter Expension Getting Started with Flutter ?? Generated with ❀️ from Dhiwise A Flutter mobile application built completely using DhiWise and Supab

DhiWise 11 Oct 23, 2022
A flutter package to cache network image fastly without native dependencies.

Fast Cached Network Image A flutter package to cache network image fastly without native dependencies, with loader, error builder, and smooth fade tra

CHRISTO 3 Sep 22, 2022
Create dart data classes easily, fast and without writing boilerplate or running code generation.

Dart Data Class Generator Create dart data classes easily, fast and without writing boilerplate or running code generation. Features The generator can

null 186 Feb 28, 2022
A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.

Simplify Equality Comparisons Overview Being able to compare objects in Dart often involves having to override the == operator as well as hashCode. No

Felix Angelov 747 Jan 8, 2023
A simple HSV color picker without any glitz or glamour.

simple_color_picker Flutter Package A simple HSV color picker without any glitz or glamour. Sample Installation dependencies: simlpe_color_picker: a

Syed Taha Ali 3 Apr 22, 2021
Backs up Android devices on Linux, macOS and Windows. Backup your device without vendor lock-ins, using insecure software or root.

Backs up Android devices on Linux, macOS and Windows. Backup your device without vendor lock-ins, using insecure software or root. Supports encryption and compression out of the box.

null 255 Dec 31, 2022