패키지, 저장소 및 앱 카테고리 검색

패키지 상세v4.3.1+1

forme

사용하기 쉬우며 확장 가능한 강력한 Flutter 폼 위젯입니다. 동기/비동기 검증을 간소화하는 풍부한 API를 제공합니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
240
좋아요
24
Pub 점수
140

패키지 설치

flutter pub add forme

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Forme는 간편한 폼 관리 및 검증을 위한 강력하고 확장 가능한 Flutter 폼 위젯입니다. 동기 및 비동기 폼 검증을 단순화하기 위해 풍부한 API를 제공하여 폼 상태와 사용자 입력을 원활하게 제어할 수 있습니다. Android, iOS, Web, macOS, Windows, Linux 등 모든 주요 플랫폼을 지원하며, 복잡한 폼 개발을 간소화하면서도 깔끔하고 가독성 있는 코드를 유지합니다. 직관적인 디자인으로 뼈대 코드 없이 강력한 폼 처리 기능을 원하는 개발자에게 이상적입니다. 이 패키지는 GitHub에서 적극적으로 유지보수되고 오픈소스로 공개되어 있습니다.

사용 사례

  • 실시간 검증을 사용하여 동적 폼 만들기
  • API 검사에 대한 비동기 검증 구현
  • 재사용 가능한 폼 컴포넌트 만들기
  • 복잡한 다단계 폼 관리
  • 상태 관리 솔루션과의 통합
  • 양식 제출 워크플로우 간소화

주요 기능

  • 폼 제어를 위한 풍부한 API
  • 내장된 동기 및 비동기 검증
  • 사용자 정의 위젯을 위한 확장 가능한 아키텍처
  • 크로스 플랫폼 호환성
  • 폼 로직과 UI의 명확한 분리
  • 중첩 및 그룹화된 폼 필드 지원

적합한 대상

  • 복잡한 Flutter 폼을 구축하는 개발자
  • 일관된 양식 검증 패턴이 필요한 팀
  • 재사용 가능한 양식 컴포넌트가 필요한 프로젝트
  • 엄격한 데이터 검증이 필요한 애플리케이션
  • UX 및 폼 피드백에 집중하는 프론트엔드 개발자

고려 사항

  • Flutter의 상태 관리에 대한 이해가 필요합니다
  • 고급 검증 규칙을 위해 추가 설정이 필요할 수 있습니다
  • 폼 추상화에 익숙하지 않은 초보자를 위한 학습 곡선
  • 검증 흐름에 Dart의 async/await에 의존합니다
  • 반응형 또는 공급자 기반 상태 관리와 가장 잘 어울림

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Web Demo

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

Simple Usage

add dependency
flutter pub add forme
flutter pub add forme_base_fields 
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,
)

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;
    });    
}
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);
get field by name
T field = formeKey.field<T extends FormeFieldState>(String name);
get form value
Map<String, dynamic> data = formeKey.value;
set form value
formeKey.value = Map<String,dynamic> value;
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,
});
get validation
FormeValidation validation = formKey.validation;
reset form
formeKey.reset();
save form
formeKey.save();
whether validate is quietly
bool quietlyValidate = formKey.quietlyValidate;
is value changed after initialed
bool isValueChanged = formeKey.isValueChanged
get all fields
List<FormeFieldState> fields = formeKey.fields;
add visitor
formeKey.addVisitor(FormeVisitor visitor);
remove visitor
formeKey.removeVisitor(FormeVisitor visitor);
rebuild form

rebuild all widgets in Forme

formeKey.rebuildForm();
FormeFieldState
get field's name
String name = field.name
whether current field is readOnly
bool readOnly = field.readOnly;
set readOnly on field
field.readOnly = bool readOnly;
whether current field is enabled
bool enabled = field.enabled;
set enabled on field
field.enabled = bool enabled;
whether field has a FocusNode
bool hasFocusNode = field.hasFocusNode
get or create a focusNode
FocusNode focusNode = field.focusNode;
whether field is focused
bool hasFocus = field.hasFocus;
request focus
field.requestFocus();
unfocus
field.unfocus();
get value
T value = field.value;
set value
field.value = T data;
reset field
field.reset();
validate
Future<FormeFieldValidateSnapshot> future = field.validate({bool quietly = false});
get validation
FormeFieldValidation validation = field.validation;
get oldValue

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

FormeOptional<T>? value = field.oldValue;

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

is value changed
bool isValueChanged = field.isValueChanged
get generic type
Type type = field.type;
whether field value is nullable
bool isNullable = field.isNullable;
get FormeState
FormeState? form = field.form;
get status
FormeFieldStatus<T> get status = field.status;
is custom validation

whether current validation is set via errorText

bool isCustomValidation = field.isCustomValidation;
get error text

typically used in display.

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

String? errorText = field.errorText;
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';
add visitor
field.addVisitor(FormeFieldVisitor visitor);
remove visitor
field.removeVisitor(FormeFieldVisitor visitor);

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'),
    ]),
)
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();
    },
),
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'),
                );
            }
        )
    ]),
)
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'),
                );
            }
        )
    ]),
)
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());
            }
        )
    ]),
)

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),
        );
    },
),

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.