Simple yet powerful form state management

Overview

formini

Working with forms shouldn't be so hard in Flutter.

Please note that the schemani/formini packages are under development. There are still some issues to resolve before this has any help for real use cases. #roadmap

Usage

Formini doesn't care what inputs you use. It however provides a TextEditingController via state.controller out of the box. For inputs other than TextFields you can use state.onChange and state.field.value.

Values are not limited only to Dart built in types. If you want to store a date field as DateTime and display the value formatted you absolutely can.

Login form using formini

import 'package:flutter/material.dart';
import 'package:formini/formini.dart';

class LoginForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Formini(
      validator: const LoginFormValidator(),
      initialValues: const {'email': 'foo'},
      onSubmit: _authenticate,
      child: Column(children: [
        ForminiStateBuilder(builder: (context, form) {
          return Column(children: [
            Text('Status: ${form.status}'),
            Text('Values: ${form.values}'),
          ]);
        }),
        ForminiField(
          name: 'email',
          builder: (context, state) => TextField(
            controller: state.controller,
            decoration: InputDecoration(
              labelText: 'Email address',
              errorText: state.field.errorText,
            ),
          ),
        ),
        ForminiField(
          name: 'password',
          builder: (context, state) => TextField(
            controller: state.controller,
            obscureText: true,
            decoration: InputDecoration(
              labelText: 'Password',
              errorText: 
                  state.field.touched ? state.field.error?.toString() : null,
            ),
          ),
        ),
        ForminiStateBuilder(builder: (context, form) {
          return RaisedButton(
            onPressed: form.submit,
            child: Text('Login'),
          );
        }),
      ]),
    );
  }

  Future<bool> _authenticate(Map<String, dynamic> credentials) async {
    // Do what ever you need to do here.
    print(credentials);
    
    return true;
  }
}

Validation

Implement the Validator interface on your validator class.

1. Option - Manually

import 'package:formini/formini.dart';

class LoginFormValidator implements Validator {
  const LoginFormValidator();

  @override
  Map<String, Exception> validate(Map<String, dynamic> values) {
    final errors = <String, Exception>{};

    if (values['email'] == null || values['email'].isEmpty) {
      errors['email'] = Exception('Email is required');
    } else if (!values['email'].contains('@')) {
      errors['email'] = Exception('Email is invalid');
    }

    if (values['password'] == null || values['password'].isEmpty) {
      errors['password'] = Exception('Password is required');
    }

    return errors;
  }
}

2. Option - Schemani (recommended)

Use schemani_formini package for validating values using schemani. Or just copy the one simple file to your project.

import 'package:schemani/schemani.dart';
import 'package:schemani_formini/schemani_formini.dart';

const loginFormValidator = SchemaniForminiValidator(MapSchema({
  'email': [Required(), Email()],
  'password': [Required()],
}));

API reference

https://pub.dev/documentation/formini

Contributing

Please open an issue or pull request in GitHub. Any help and feedback is much appreciated.

Licence

MIT

Roadmap

  • Support for nested values maps
  • Support for lists
  • Async validation
  • Unit testing after refactoring
    • Separate core out from the Flutter stuff
  • Benchmarking
Comments
  • Support for nested form values

    Support for nested form values

    Formini should support nested values inside Maps.

    const user = {
      'email': '[email protected]',
      'profile': {
        'avatar': 'https://example.org',
      },
    }
    

    In Angular this is handled by setting a new formGroup scope for the nested values. Should we do something similar?

    Maybe even diverge from the Formik API and lean more against the Angular forms API removing the Formini widget altogether.

    opened by jaripekkala 1
  • State resets on hot reload

    State resets on hot reload

    This will fix itself when we provide the FormStateProvider widget thus the state class won't be created on render.

    Related issues

    • https://github.com/vantageoy/formini/issues/8
    • https://github.com/vantageoy/formini/issues/2
    bug 
    opened by jaripekkala 0
  • Usage with TextField

    Usage with TextField

    Currently there aren't perfect solution for the most common form field.

    TextFormField

    Works. However formini state resets on hot reload and TextFormField's state doesn't causing the input show previous (mismatching with state) value.

    FormControlBuilder(
      control: user.email,
      builder: (context, state) => TextFormField(
        initialValue: state.value,
        onChanged: user.email.setValue,
        decoration: InputDecoration(
          labelText: 'Email address',
          errorText: state.dirty ? state.error?.toString() : null,
        ),
      ),
    )
    

    TextField

    Works. However the TextEditingController also controls the cursor state so creating a new control for every value causes the cursor to go to the beginning of the value.

    FormControlBuilder(
      control: user.email,
      builder: (context, state) => TextField(
        controller: TextEditingController(text: state.value),
        onChanged: user.email.setValue,
        decoration: InputDecoration(
          labelText: 'Email address',
          errorText: state.dirty ? state.error?.toString() : null,
        ),
      ),
    )
    

    FormEditableTextAdaptor

    Works pretty much perfectly once done right. However formini doesn't provide form fields and this widget got too dangerously close to that area thus deleted from the codebase.

    https://github.com/vantageoy/formini/blob/21af81ba70c1eebcbdc826ef292fe323850f7b92/lib/src/flutter/adaptors/form_editable_text_adaptor.dart

    FormEditableTextAdaptor(
      control: user.email,
      builder: (context, controller, state) => TextField(
        controller: controller,
        decoration: InputDecoration(
          labelText: 'Email address',
          errorText: state.dirty ? state.error?.toString() : null,
        ),
      ),
    )
    
    bug help wanted 
    opened by jaripekkala 1
  • Value accessors

    Value accessors

    final data = {
      'product': {
        'id': 2,
        'name': 'Foo',
      },
      'product_id': 2,
    };
    
    final form = FormGroup({
      'product_id': FormControl(data['product'], [Required()]),
    });
    
    assert(form.value != {'product_id': 2});
    

    Use cases: autocompletes with initial value, single stored values controlled via multiple form controls (date & time fields separate however stored as datetimes)

    enhancement question 
    opened by jaripekkala 0
  • Async validation

    Async validation

    Validation is now triggered asynchronously by design however run synchronously.

    Supporting async validations would allow developers to validate example has the username be taken by making a network request.

    enhancement 
    opened by jaripekkala 0
  • Core design and refactoring

    Core design and refactoring

    Should we depend on the bloc and flutter_bloc packages so heavily?

    If we decide not to we could separate the form handling core from the flutter stuff.

    Tests are on hold until refactor.

    opened by jaripekkala 2
A powerful state machine for MobX management, that can be used in almost any application state.

A powerful state machine for MobX management, which can be used in almost any application state. It has 3 states - loading, success, error - and is pe

Daniel Magri 8 Oct 31, 2022
A simple yet powerful Flutter plugin for showing Toast at Android, iOS and Web.

Flutter Toast A simple yet powerful Flutter plugin for showing Toast at Android and iOS. Features: Native Toast Pure Flutter Toaster Installation Add

Eyro Labs 5 Dec 13, 2021
Easy Form State Management using BLoC pattern

?? Dart and Flutter Package ?? Easy Form State Management using BLoC pattern ?? Wizard/stepper forms, asynchronous validation, dynamic and conditional fields, submission progress, serialization and more! ??

GiancarloCode 406 Jan 8, 2023
⚡FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps.

⚡ FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps. It ca

Piyush 21 Dec 22, 2022
A light, powerful and reactive state management for Flutter Apps.

A light, powerful and reactive state management. Features ⚡️ Build for speed. ?? Reduce boilerplate code significantly. ?? Improve code readability. ?

2devs 3 Dec 15, 2022
Flutter form fields designed to take much of the burden of form-related coding off the programmer's back — masks, validations, keyboard type, etc.

well_formed Contents Overview Getting Started Demo application References Overview Well-Formed Widget Fields - Well-Formed - is a collection of Flutte

Dartoos 7 Nov 2, 2022
User auth form - Signup and signin user auth form with ability to stay signed in and have an option to signout.

user_auth_form SIgnup and signin user authentification form Getting Started This project is a starting point for a Flutter application. A few resource

null 0 Jan 6, 2022
A Flutter package that provides a dropdown form field using a dropdown button inside a form field.

Dropdown form field A dropdown form field using a dropdown button inside a form field. Demo Features Can be used as regular form field. Simple to impl

Carlos Eugenio Torres 72 Jan 1, 2023
Form builder image picker - Form builder image picker for flutter

form_builder_image_picker Field for picking image(s) from Gallery or Camera for

Ferri Sutanto 0 Jan 28, 2022
Jannis 0 Jan 29, 2022
State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Flutter Community 70 Sep 28, 2022
An extension to the bloc state management library which lets you create State Machine using a declarative API

An extension to the bloc state management library which lets you create State Machine using a declarative API

null 25 Nov 28, 2022
Practice building basic animations in apps along with managing app state by BLoC State Management, Flutter Slider.

Practice building basic animations in apps along with managing app state by BLoC State Management including: Cubit & Animation Widget, Flutter Slider.

TAD 1 Jun 8, 2022
Shopify Tag and Product Management App using Flutter and Riverpod State Management

Myshopify App A Simple Flutter Application project to get List of Tags, Products and Product Details from shopify https://shopicruit.myshopify.com/adm

Idowu Tomiwa 5 Nov 12, 2022
A simple yet elegant tip calculator created using flutter framework and dart language.

CAL- TIP, A TIP CALCULATOR APPLICATION A simple yet elegant tip calculator created using flutter framework and dart language. As the name suggests, th

Nitin Verma 0 Dec 26, 2021
This project follows the Reso Coder course for flutter test-driven-development with clean architecture and BloC state management for a random trivia simple app.

This project follows the Reso Coder course for flutter test-driven-development with clean architecture and BloC state management for a random trivia simple app.

Tomas B Sarmiento Abella 1 Jan 5, 2022
Building a simple Flutter app for understanding the BLoC State Management including: Cubit, Managing Route & showSnackBar.

Building a simple Flutter app for understanding the BLoC State Management including: Cubit, Managing Route & showSnackBar.

TAD 8 Dec 3, 2022
Building a simple Flutter app * Switch Theme * for understanding the BLoC State Management including: Cubit Communications with StreamSubscription & Managing Route.

Building a simple Flutter app * Switch Theme * for understanding the BLoC State Management including: Cubit Communications with StreamSubscription & Managing Route.

TAD 1 Oct 3, 2022
Practice code of simple flutter app to explain how provider works as across the widget state management.

vdo A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this is y

Syed Uzair 9 Nov 7, 2022