forme 4.3.1+1 copy "forme: ^4.3.1+1" to clipboard
forme: ^4.3.1+1 copied to clipboard

a powerful flutter form widget ,easy to use and extend. provide rich api to simplify form control and sync|async validation

Web Demo #

https://www.qyh.me/forme3/index.html

Simple Usage #

add dependency #

flutter pub add forme
flutter pub add forme_base_fields 
copied to clipboard

create forme #

FormeKey key = FormeKey();// formekey is a global key , also  used to control form
Widget child = FormeTextField(name:'username',decoration:const InputDecoration(labelText:'Username'));
Widget forme = Forme(
	key:key,
	child:child,
)
copied to clipboard

Forme Attributes #

Attribute Required Type Description
key false FormeKey a global key, also used to control form
child true Widget form content widget
onFieldStatusChanged false FormeFieldStatusChanged listen form field's status change
initialValue false Map<String,dynamic> initialValue , will override FormField's initialValue
onWillPop false WillPopCallback Signature for a callback that verifies that it's OK to call Navigator.pop
quietlyValidate false bool if this attribute is true , will not display error text
autovalidateMode false AutovalidateMode auto validate form mode
autovalidateByOrder false bool whether auto validate form by order
onFieldsRegistered false function listen registered fields
onFieldsUnregistered false function listen unregistered fields
onInitialized false function typically used to register visitors

FormeField #

attributes supported by all FormeField #

Attribute Required Type Description
name false String field's id,should be unique in form
readOnly false bool whether field should be readOnly,default is false
builder true FormeFieldBuilder build field content
enabled false bool whether field is enabled or not default
quietlyValidate true bool false will not display error text
initialValue true T default value of field , will overwritten by Forme initialValue
asyncValidatorDebounce false Duration async validate debounce , default is 500ms
autovalidateMode false AutovalidateMode autovalidate mode
onStatusChanged false FormeFieldStatusChanged listen value
onInitialized false FormeFieldInitialized typically used to register visitors
onSaved false FormeFieldSetter triggered when form saved
validator false FormeValidator sync validator
asyncValidator false FormeAsyncValidator async validator
decorator false FormeFieldDecorator used to decorate a field
order false int order of field
requestFocusOnUserInteraction false bool whether request focus when field value changed by user interaction
validationFilter false function used to determine whether perform a validation or not
focusNode false FocusNode FocusNode

Validation #

Async Validation #

you can specify an asyncValidator on FormeField , the unique difference between validator and asyncValidator is asyncValidator return a Future<String> and validator return a String

when to perform an async validation

if FormeField.autovalidateMode is AutovalidateMode.disabled , asyncValidator will never be performed unless you call validate on FormeFieldState manually.

if you specify both validator and asyncValidator , asyncValidator will only be performed after validator return null.

if validationFilter is specified and not passed. asyncValidator will not be performed

debounce

you can specify a debounce on FormeField , debounce will not worked when you manually call validate on FormeFieldState

whether validation itself is valid

in some cases,when an async validation is performing , another validation on same field is performed,in this case ,previous validation is invalid , so if you want to update UI before return validation result in async validator , you need to validate it first,eg:

asyncValidator:(field,value,isValid){
    return Future.delayed(const Duration(seconds:2),(){
        if(isUnexceptedValue(value)) {
            if(isValid()){
                updateUI();
            }
            return 'invalid';
        }
        return null;
    });    
}
copied to clipboard

FormeValidates #

you can use FormeValidates to simplify your validators

Validator Name Support Type When Valid When Invalid
notNull dynamic value is not null value is null
size Iterable Map String 1. value is null 2. max & min is null 3. String's length or Collection's size is in [min,max] String's length or Collection's size is not in [min,max]
min num 1. value is null 2. value is bigger than min value is smaller than min
max num 1. value is null 2. value is smaller than max value is bigger than max
notEmpty Iterable Map String 1. value is not null 2. String's length or Collection's size is bigger than zero 1. value is null 2. String's length or Collection's size is zero
notBlank String 1. value is null 2. value.trim()'s length is not null value'length is zero after trimed
positive num 1. value is null 2. value is bigger than zero value is smaller than or equals zero
positiveOrZero num 1. value is null 2. value is bigger than or equals zero value is smaller than zero
negative num 1. value null 2. value is smaller than zero value is bigger than or equals zero
negativeOrZero num 1. value null 2. value is smaller than or equals zero value is bigger than zero
pattern String 1. value null 2. value matches pattern value does not matches pattern
email String 1. value null 2. value is a valid email value is not a valid email
url String 1. value is null 2. value is empty or value is a valid url value is not a valid url
range num 1. value null 2. value is in range value is out of range
equals dynamic 1. value null 2. value is equals target value value is not equals target value
any T any validators is valid every validators is invalid
all T all validators is valid any validators is invalid

when you use validators from FormeValidates , you must specify at least one errorText , otherwise errorText is an empty string

Methods #

FormeKey|FormeState #

whether form has a name field

bool hasField = formeKey.hasField(String name);
copied to clipboard

get field by name

T field = formeKey.field<T extends FormeFieldState>(String name);
copied to clipboard

get form value

Map<String, dynamic> data = formeKey.value;
copied to clipboard

set form value

formeKey.value = Map<String,dynamic> value;
copied to clipboard

validate

you can use FormeValidateSnapshot.isValueChanged to check whether form value is changed duration this validation , if is changed , typically means this validation is invalid , you should not submit your form even though validation is passed

Future<FormeValidateSnapshot> future = formKey.validate({
    bool quietly = false,
    Set<String> names = const {},
    bool clearError = false,
    bool validateByOrder = false,
});
copied to clipboard

get validation

FormeValidation validation = formKey.validation;
copied to clipboard

reset form

formeKey.reset();
copied to clipboard

save form

formeKey.save();
copied to clipboard

whether validate is quietly

bool quietlyValidate = formKey.quietlyValidate;
copied to clipboard

is value changed after initialed

bool isValueChanged = formeKey.isValueChanged
copied to clipboard

get all fields

List<FormeFieldState> fields = formeKey.fields;
copied to clipboard

add visitor

formeKey.addVisitor(FormeVisitor visitor);
copied to clipboard

remove visitor

formeKey.removeVisitor(FormeVisitor visitor);
copied to clipboard

rebuild form

rebuild all widgets in Forme

formeKey.rebuildForm();
copied to clipboard

FormeFieldState #

get field's name

String name = field.name
copied to clipboard

whether current field is readOnly

bool readOnly = field.readOnly;
copied to clipboard

set readOnly on field

field.readOnly = bool readOnly;
copied to clipboard

whether current field is enabled

bool enabled = field.enabled;
copied to clipboard

set enabled on field

field.enabled = bool enabled;
copied to clipboard

whether field has a FocusNode

bool hasFocusNode = field.hasFocusNode
copied to clipboard

get or create a focusNode

FocusNode focusNode = field.focusNode;
copied to clipboard

whether field is focused

bool hasFocus = field.hasFocus;
copied to clipboard

request focus

field.requestFocus();
copied to clipboard

unfocus

field.unfocus();
copied to clipboard

get value

T value = field.value;
copied to clipboard

set value

field.value = T data;
copied to clipboard

reset field

field.reset();
copied to clipboard

validate

Future<FormeFieldValidateSnapshot> future = field.validate({bool quietly = false});
copied to clipboard

get validation

FormeFieldValidation validation = field.validation;
copied to clipboard

get oldValue

if value changed , you can use this method to get previous value

FormeOptional<T>? value = field.oldValue;
copied to clipboard

if value is null , means field's value is never changed before

is value changed

bool isValueChanged = field.isValueChanged
copied to clipboard

get generic type

Type type = field.type;
copied to clipboard

whether field value is nullable

bool isNullable = field.isNullable;
copied to clipboard

get FormeState

FormeState? form = field.form;
copied to clipboard

get status

FormeFieldStatus<T> get status = field.status;
copied to clipboard

is custom validation

whether current validation is set via errorText

bool isCustomValidation = field.isCustomValidation;
copied to clipboard

get error text

typically used in display.

if FormeField.quietlyValidate or Forme.quietlyValidate is true , you'll always get null

String? errorText = field.errorText;
copied to clipboard

set error text

if errorText is null , reset validation.

field will rebuild after this method called. if field has validators , a new validation maybe performed , in this case ,custom validation will be overwritten by new validation. use FormeField.validationFilter to avoid this

will not worked on disabled fields

field.errorText = 'custom error';
copied to clipboard

add visitor

field.addVisitor(FormeFieldVisitor visitor);
copied to clipboard

remove visitor

field.removeVisitor(FormeFieldVisitor visitor);
copied to clipboard

Listeners #

listeners is helpful when you build widgets which depends on status of FormeField or Forme , you must used them inside in Forme or FormeField

FormeFieldStatusListener #

will rebuild whenever field's status changed , use filter to avoid unnecessary rebuild.

eg:

Forme(
    child:Column(children:[
        FormeFieldStatusListener(
            filter:(status) => status.isValueChanged,/// if you only want to  rebuild when value changed
            name:'name',
            builder:(context,status,child){
                return Text('current value:${status.value}')
            }
        ),
        FormeTextField(name:'name'),
    ]),
)
copied to clipboard

FormeFieldsValidationListener #

will rebuild whenever validation of any field changed

eg:

FormeFieldsValidationListener(
      names: const {'password', 'confirm'},
      builder: (context, validation) {
        if (validation == null) {
          return const SizedBox();
        }
        if (validation.isInvalid) {
          return Padding(
            padding: const EdgeInsets.only(left: 24),
            child: Text(
              validation.validations.values
                  .where((element) => element.isInvalid)
                  .first
                  .error!,
              style: _getErrorStyle(),
            ),
          );
        }
        return const SizedBox.shrink();
    },
),
copied to clipboard

FormeValidationListener #

will rebuild whenever form validation changed , useful when you want to create a submit button which only clickable when form validation passed

eg:

Forme(
    child:Column(children:[
        ...
        FormeValidationListener(
            builder:(context,validation,child){
                return TextButton(
                    onPressed:validation.isValid ? submit:null,
                    child:const Text('submit'),
                );
            }
        )
    ]),
)
copied to clipboard

FormeIsValueChangedListener #

will rebuild whenever form value changed , useful when you want to create a reset button which depends on form value changed or not

eg:

Forme(
    child:Column(children:[
        ...
        FormeIsValueChangedListener(
            builder:(context,isValueChanged,child){
                return TextButton(
                    onPressed:isValueChanged ? reset:null,
                    child:const Text('reset'),
                );
            }
        )
    ]),
)
copied to clipboard

FormeValueListener #

will rebuild whenever form value changed , typically used in debug .

eg:

Forme(
    child:Column(children:[
        ...
        FormeValueListener(
            builder:(context,value,child){
                return Text(value.toString());
            }
        )
    ]),
)
copied to clipboard

custom field #

FormeField<String>(
    name: 'customField',
    initialValue: 'currentValue',
    builder: (FormeFieldState<String> state) {
        return TextButton(
        onPressed: () {
           state.readOnly? null: state.didChange('newValue');
        },
        child: Text(state.value),
        );
    },
),
copied to clipboard
25
likes
140
points
410
downloads

Publisher

verified publisherqyh.me

Weekly Downloads

2024.09.25 - 2025.04.09

a powerful flutter form widget ,easy to use and extend. provide rich api to simplify form control and sync|async validation

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on forme