form_builder 1.0.0-beta.3 copy "form_builder: ^1.0.0-beta.3" to clipboard
form_builder: ^1.0.0-beta.3 copied to clipboard

outdated

flutter row-column based form builder, build form quickly,create field fast,less code,more powerful

flutter_form_builder #

basic usage #

FormManagement formManagement = FormManagement();

Widget form = FormBuilder(
      {bool readOnly,//set form's readonly state
      bool visible, // set form's visible state
      FormThemeData? formThemeData, //set themedata of form 
      this.formManagement,
	.textField(
          name: 'username',
          labelText: 'username',
          clearable: true,
          validator: (value) =>
              value.isEmpty ? 'username can not be empty !' : null,
        )
        .switchInline(
          name: 'switch1',
          onChanged: (value) => print('switch1 value changed $value'),
        )
        .nextLine()
        .textField(
            name: 'password',
            hintText: 'password',
            obscureText: true,
            passwordVisible: true,
            clearable: true,
            toolbarOptions: ToolbarOptions(copy: false, paste: false),
            onChanged: (value) => print('password value changed $value'),
            flex: 1)
        .textButton(
            onPressed: () {
              formManagement
                  .getFormFieldManagement('password')
                  .textSelectionManagement
                  .selectAll();
            },
            label: 'button',
            name: 'button')
        .nextLine()
        .numberField(
          name: 'age',
          hintText: 'age',
          clearable: true,
          flex: 3,
          min: -18,
          max: 99,
          decimal: 0,
          onChanged: (value) => print('age value changed $value'),
          validator: (value) => value == null ? 'not empty' : null,
        )
        .checkboxGroup(
          items: FormBuilder.toCheckboxGroupItems(['male', 'female']),
          name: 'checkbox',
          split: 2,
          label: 'sex',
          onChanged: (value) => print('checkbox value changed $value'),
          validator: (value) => value.isEmpty ? 'pls select sex' : null,
        );

form widget tree #

Column 
  Row
    FormField 

base field widget tree #

base field is default form field

Flexible(
  fit: state.visible ? FlexFit.tight : FlexFit.loose,
  child: Padding(
    padding: state.padding ?? const EdgeInsets.all(5),
    child: Visibility(
      maintainState: true,
      child: BaseFormField,
      visible: state.visible,
    ),
  ),
  flex: state.flex,
)

methods #

FormManagement #

get FormThemeData

FormThemeData formThemeData => formManagement.formThemeData

set FormThemeData

formManagement.formThemeData = FormThemeData(themeData);// system theme
formManagement.formThemeData = DefaultFormTheme(); //default theme from  https://github.com/mitesh77/Best-Flutter-UI-Templates/blob/master/best_flutter_ui_templates/lib/hotel_booking/filters_screen.dart

whether has a name field

bool hasField => formManagement.hasField(String name);

whether form is visible

bool visible = formManagement.visible;

hide|show form

formManagement.visible = true|false;

whether form is readOnly

bool readOnly = formManagement.readOnly;

set form readonly|editable

formManagement.readOnly = true|false;

get rows of form

int rows = formManagement.rows;

create FormFieldManagement

FormFieldManagement formFieldManagement =  newFormFieldManagement(String name);

create FormPositionManagement

FormPositionManagement formPositionManagement =  newFormPositionManagement(int row,{int? column});

get form data

only contains field which has a name

Map<String,dynamic> dataMap = formManagement.data;

reset form

formManagement.reset();

validate form

formManagement.validate();

whether form is valid

unlike validate method, this method won't display error msg

bool isValid = formManagement.isValid

get error

Map<String, String> errorMap = formManagement.error;

create FormRowManagement

FormRowManagement formRowManagement = formManagement.newFormRowManagement(int row);

FormFieldManagement #

whether field is focusable

bool focusable => formFieldManagement.focusable

whether field is focused

bool focused => formFieldManagement.hasFocus

focus|unfocus field

formFieldManagement.focus = true|false

set focuslistener

call this method in WidgetsBinding.instance!.addPostFrameCallback

formFieldManagement.focusListener = (key,hasFocus){
  // when key is null, root node focused
  // otherwise sub node focused
}

get ValueFieldManagement

field must be a valuefield ,otherwise an error will be throw

ValueFieldManagement ValueFieldManagement  = formFieldManagement.valueFieldManagement 

whether field is ValueField

bool isValueField = formFieldManagement.isValueField;

whether field support textSelection

bool supportTextSelection = formFieldManagement.supportTextSelection

get TextSelectionManagement

if field don't support textSelection ,an error will be throw

TextSelectionManagement  textSelectionManagement = formFieldManagement.textSelectionManagement

whether field is readOnly

bool readOnly = formFieldManagement.readOnly;

set readOnly

formFieldManagement.readOnly = true|false

whether field is visible

bool visible = formFieldManagement.visible;

set visible

formFieldManagement.visible = true|false

get field's state value

T? value => formFieldManagement.getState<T>(String stateKey);

update field's state

see supported states for every field here

formFieldManagement.update({});

update one field state

see supported states for every field here

formFieldManagement.update1(String key,dynamic value);

ValueFieldManagement #

get value

dynamic value => valueFieldManagement.value

set value

valueFieldManagement.value = value;//will trigger onChanged
valueFieldManagement.setValue(dynamic value,{bool trigger})

whether field is valid

this method won't display error msg

bool isValid = valueFieldManagement.isValid;

validate field

this method will display error and return whether field is valid

bool isValid = valueFieldManagement.validate();

reset field

valueFieldManagement.reset();

get error

String? error = valueFieldManagement.error;

FormPositionManagement #

whether all fields is readOnly

bool get readOnly => formPositionManagement.readOnly;

set readOnly on all fields

formPositionManagement.readOnly = true|false;

whether at least one field is visible

bool visible = formPositionManagement.visible;

set visible on all fields

formPositionManagement.visible = true|false;

field states #

ClearableTextFormField #

name Type nullable
labelText String true
hintText String true
keyboardType TextInputType true
autofocus bool false
maxLines int true
maxLength int true
clearable bool false
prefixIcon Widget true
inputFormatters List< TextInputFormatter> true
style TextStyle true
toolbarOptions ToolbarOptions true
selectAllOnFocus bool false
suffixIcons List< Widget> true
textInputAction TextInputAction true
inputDecorationTheme InputDecorationTheme true

DateTimeFormField #

name Type nullable
labelText String true
hintText String true
maxLines int false
useTime bool false
formatter DateTimeFormatter true
style TextStyle true
inputDecorationTheme InputDecorationTheme true

NumberFormField #

name Type nullable
labelText String true
hintText String true
autofocus bool false
clearable bool false
prefixIcon Widget true
style TextStyle true
suffixIcons List< Widget> true
textInputAction TextInputAction true
inputDecorationTheme InputDecorationTheme true
decimal int false
max max true
min min true

CheckboxGroupFormField #

name Type nullable
label String true
split int false
items List< CheckboxGroupItem> false
errorTextPadding EdgeInsets false
labelPadding EdgeInsets false

RadioGroupFormField #

name Type nullable
label String true
split int false
items List< RadioGroupItem> false
errorTextPadding EdgeInsets false
labelPadding EdgeInsets false

SelectorFormField #

name Type nullable
labelText String true
hintText String true
multi bool false
clearable bool false
inputDecorationTheme InputDecorationTheme true

SliderFormField #

name Type nullable
label String true
max double false
min double false
divisions int false
contentPadding EdgeInsets false
labelPadding EdgeInsets false

RangeSliderFormField #

name Type nullable
label String true
max double false
min double false
divisions int false
contentPadding EdgeInsets false
labelPadding EdgeInsets false

SwitchGroupFormField #

name Type nullable
label String true
items List< SwitchGroupItem> false
hasSelectAllSwitch bool false
selectAllPadding EdgeInsets false
errorTextPadding EdgeInsets false
labelPadding EdgeInsets false

FilterChipFormField #

name Type nullable
label String true
items List< FilterChipItem<T>> false
pressElevation double true
errorTextPadding EdgeInsets false
labelPadding EdgeInsets false

currently support fields #

field return value nullable
ClearableTextFormField string false
CheckboxGroupFormField List< int> false
RadioGroupFormField T true
DateTimeFormField DateTime true
SelectorFormField List< T> false
SwitchGroupFormField List< int> false
SwitchInlineFormField bool false
NumberFormField num true
SliderFormField double false
RangeSliderFormField RangeValues false
FilterChipFormField List< T> false

build your own form field #

build a value field #

if you want to build a nullable value field ,just extends BaseValueField

this is an example:

class CustomNullableValueField<T> extends BaseValueField<T> {
  CustomNullableValueField({
    String? name,//important !,used to maintain state and used as a key when you get data via FormManagement.data
    required T value,
    String? label,
    TextStyle? textStyle,
    T? initialValue,
    ValueChanged<T?>? onChanged,
    FormFieldValidator<T>? validator,
  }) : super(
          {
            'label': StateValue<String?>(label),
            'textStyle': StateValue<TextStyle?>(textStyle),
          }, //this is a initStateMap
          name:name,
          initialValue: initialValue,
          validator: validator,
          onChanged: onChanged,
          builder: (state) {
            bool readOnly = state.readOnly;
            Map<String, dynamic> stateMap = state.currentMap;
            ThemeData themeData = state.formThemeData;
            // state is ValueFieldState<T>,if you override ValueFieldState,you can cast it as your custom ValueFieldState,in this example you can cast it to _CustomNullableValueFieldState,you can get name via state.name(nullable),you can also get row|column|flex|inline to help you building your widget
            // readOnly : whether this field should readOnly
            // stateMap : can be regarded as the lastest initStateMap , user can change stateMap var FormFieldManagement's update|removeState|directly set state, in this example ,you should get label&textStyle form stateMap rather than directly use them
            // themeData : ThemeData
            return Row(
              children: [
                Text(
                  stateMap['label'] ??
                      'radio', //don't use just label here,you should get lastest label from stateMap,the key is initStateMap's label key
                  style: stateMap['textStye'],
                ),
                Radio<T>(
                  focusNode: state
                      .focusNode, //state has prepared a focusnode for you,just use it rather than create a new one
                  activeColor: themeData.primaryColor,
                  groupValue: state.value,
                  value: value,
                  onChanged:
                      readOnly ? null : (value) => state.didChange(value),
                )
              ],
            );
          },
        );

  @override
  _CustomNullableValueFieldState<T> createState() =>
      _CustomNullableValueFieldState();
}

if you also want to build custom ValueFieldState,extends it !

class _CustomNullableValueFieldState<T> extends BaseValueFieldState<T>
    with TextSelectionManagement // if you form field support textselection
{
  late final TextEditingController
      textEditingController; //just an example here !

  @override
  void initState() {
    super.initState();
    textEditingController = TextEditingController(
        text:
            widget.initialValue == null ? '' : widget.initialValue.toString());
  }

  @override
  void reset() {
    super.reset();
    textEditingController.text =
        widget.initialValue == null ? '' : widget.initialValue.toString();
  }

  @override
  void dispose() {
    textEditingController.dispose();
    super.dispose();
  }

  @override
  void selectAll() {
    setSelection(0, textEditingController.text.length);
  }

  @override
  void setSelection(int start, int end) {
    TextSelectionManagement.setSelectionWithTextEditingController(
        start, end, textEditingController);
  }
}

the last step is insert your field

FormBuilder.field(
    field: CustomNullableValueField<String>(
        onChanged: (value) => print(value), value: '123')),

build a nonnull value field is almost the same,just extends BaseNonnullValueField

this is an example:


class CustomNonnullableValueField extends BaseNonnullValueField<bool> {
  CustomNonnullableValueField({
    String? label,
    TextStyle? textStyle,
    required bool initialValue,
    ValueChanged<bool>? onChanged,
    NonnullFieldValidator<bool>? validator,
  }) : super(
          {
            'label': StateValue<String?>(label),
            'textStyle': StateValue<TextStyle?>(textStyle),
          },
          initialValue: initialValue,
          validator: validator,
          onChanged: onChanged,
          builder: (state) {
            bool readOnly = state.readOnly;
            Map<String, dynamic> stateMap = state.currentMap;
            ThemeData themeData = state.formThemeData;
            return Row(
              children: [
                Text(
                  stateMap['label'] ?? 'checkbox',
                  style: stateMap['textStye'],
                ),
                Checkbox(
                  activeColor: themeData.primaryColor,
                  value: state.value,
                  onChanged: readOnly ? null : (value) => state.didChange(value),
                )
              ],
            );
          },
        );
}

build a commonfield #

class Label extends BaseCommonField {
  final String label;
  Label(this.label)
      : super(
          {'label': StateValue<String>(label)},
          builder: (state) {
            Map<String, dynamic> stateMap = state.currentMap;
            ThemeData themeData = state.formThemeData;
            return Text(
              stateMap['label'],
              style: TextStyle(
                  fontSize: 18, color: themeData.primaryColor),
            );
          },
        );
}

build a Stateless Field #

FormBuilder.field(field: Builder(builder: (context) {
          BuilderInfo info = BuilderInfo.of(context);
          Position position = info.position;
          return Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'I\'m a stateless field',
                  style: TextStyle(fontSize: 20),
                ),
                Container(
                  color: info.formThemeData.primaryColor.withOpacity(0.3),
                  child: ListView(
                    shrinkWrap: true,
                    children: [
                      createRow('row', '${position.row}'),
                      createRow('column', '${position.column}'),
                      createRow('inline', '${info.inline}'),
                    ],
                  ),
                )
              ],
            ),
            flex: 1,
          );
        }))

project status #

beta

develop plan #

  1. performance test
  2. support more fields
1
likes
0
points
240
downloads

Publisher

unverified uploader

Weekly Downloads

flutter row-column based form builder, build form quickly,create field fast,less code,more powerful

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on form_builder