Giter Club home page Giter Club logo

giancarlocode / form_bloc Goto Github PK

View Code? Open in Web Editor NEW
460.0 19.0 195.0 57.17 MB

๐Ÿ”ฅ 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! ๐Ÿ”ฅ

Home Page: https://GiancarloCode.github.io/form_bloc/

Dart 89.37% Kotlin 0.03% Swift 0.43% Objective-C 0.01% HTML 0.43% CMake 4.17% C++ 5.31% C 0.26%
flutter bloc form dart rxdart form-validation forms reactive-x form-handler

form_bloc's Introduction

form_bloc

Package Pub
form_bloc pub package
flutter_form_bloc pub package

Easy Form State Management using BLoC pattern. Separate the Form State and Business Logic from the User Interface.

  • Synchronous Field Validation
  • Asynchronous Field Validation
  • Easy Loading and Initializing
  • Wizard / Stepper Forms
  • Submission Progress
  • Success / Failure Response
  • Serializable Form
  • Submission Errors to Fields
  • Dynamic Fields
  • Conditional Fields
  • List Fields
  • Group Fields
  • CRUD Support
  • Beautiful Built-In Widgets

Examples

form_bloc's People

Contributors

aaassseee avatar aideric avatar akshay-akkay avatar brex900 avatar danaru87 avatar daninow avatar giancarlocode avatar hoffmannkrzysztof avatar jackliu-gulu avatar simonebressan avatar wahdanz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

form_bloc's Issues

Dart Close Sinks Warning

Above every bloc field I create in my classes I have to keep putting // ignore: close_sinks. I know that it closes the fields automatically so I don't have to call the close() method myself but is there anything that I or you can do? I know it's just a warning and not an error but it's still annoying.

Validators are not fired when field is empty.

From 0.11.0 there is isRequired flag.
But if I do not need the built in required validation?
What if I want custom message for required case?

In case if I do not pass the isRequired the validators are not fired if the input value is empty.

The previous solution with validators array way clear and usable. The updated one is not so flexible...

Is there a possibility to revert error handling to previous version?

[Proposal] Remove state.fieldBlocFromPath('path') and add methods to get each Type of FieldBloc

Currently when you want to obtain a FieldBloc you must do the casting later if you want to have static analysis.

state.fieldBlocFromPath('email').asTextFieldBloc

The proposal is to eliminate state.fieldBlocFromPath('path') and add methods that do the casting automatically, reducing the amount of code.

Option 1:

state.textFieldBloc('path');
state.booleanFieldBloc('path');
state.selectFieldBloc<T>('path');
state.multiSelectFieldBloc<T>('path');
state.inputFieldBloc<T>('path');
state.groupFieldBloc('path');
state.fieldBlocList<T>('path');
Option 2 (discarded)
state.getTextFieldBloc('path');
state.getBooleanFieldBloc('path');
state.getSelectFieldBloc<T>('path');
state.getMultiSelectFieldBloc<T>('path');
state.getInputFieldBloc<T>('path');
state.getGroupFieldBloc('path');
state.getFieldBlocList('path');

Option 3:

state.textFieldBlocOf('path');
state.booleanFieldBlocOf('path');
state.selectFieldBlocOf<T>('path');
state.multiSelectFieldBlocOf<T>('path');
state.inputFieldBlocOf<T>('path');
state.groupFieldBlocOf('path');
state.fieldBlocListOf<T>('path');

[Proposal] change onSubmitting() to onSubmitting(state)

onSubmitting is only called when all fields are valid and submit was called

But this does not prevent you from changing the value of a field while isSubmitting is running, and causing some unexpected behavior.

In most cases:

  @override
  Stream<FormBlocState<Success, Failure>> onSubmitting() async* {
    state.fieldBlocFromPath('email').value; // "[email protected]" -> valid
  }

Unexpected behavior, incorrect and invalid value

  @override
  Stream<FormBlocState<Success, Failure>> onSubmitting() async* {
    // Do it some asynchronous process, for example open a database; 

    // While somewhere in the application update the value of this field 
    // for something invalid or other value, for example the user from the UI
    // state.fieldBlocFromPath('email').updateValue('invalid email);

    state.fieldBlocFromPath('email').value; // "invalid email" -> invalid
  }

Proposal:

Add state parameter to onSubmitting, this will be a snapshot of the valid state, so you will don't have any unexpected behavior

  @override
  Stream<FormBlocState<Success, Failure>> onSubmitting(
    FormBlocState<Sucess, Failure> state,
  ) async* {
    // Do it some asynchronous process, for example open a database; 

    // While somewhere in the application update the value of this field for something invalid, for example the user from the UI
    // state.fieldBlocFromPath('email').updateValue('invalid email');

    state.fieldBlocFromPath('email').value; // "[email protected]" -> valid
}

Note:

This will be almost mandatory, if we want to have a correct behavior if we add in the future an autoSumbit / autoSaved. #39


Do you have any suggestion?

Unexpected contentPadding for DateTimeFieldBloc

Hi. Thanks again for 0.11.0 update.

I tried to use the DateTimeFieldBloc but I've found some unexpected behaviour.

if (decoration.contentPadding == null) {
      decoration = decoration.copyWith(
        contentPadding: decoration.border is OutlineInputBorder ||
                Theme.of(context).inputDecorationTheme.border
                    is OutlineInputBorder
            ? EdgeInsets.fromLTRB(12, 20, 0, 20)
            : EdgeInsets.fromLTRB(12, 12, 0, 12),
      );
    }

This caused datetime input to look a little bit bigger than the regular input.
I dig through the textfield initial implementation and found that in dense decoration mode(isDense: true) the content padding slightly different

 if (decoration.filled == true) { // filled == null same as filled == false
        contentPadding = decorationContentPadding ?? (decorationIsDense
          ? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
          : const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));

This took me 20-30 minutes to adopt the DaterTimeFieldBloc for my needs.
Also this design choice makes the DateTimeFieldBloc to ignore isDense prop in decoration.

The same relates to the padding around both DateTimeFieldBloc and TextFieldBloc which is slightly unexpected to have)

Do we actually need those design tweaks?
From my perspective the main goal of built in components is to carefully pass through the options without any modifications.

[Proposal] Add method to FormBlocState to get the current value of FieldBloc easily

Currently when you want to obtain the current value of a FieldBloc you must get the FieldBloc and then call value property.

state.fieldBlocFromPath('email').asTextFieldBloc.value;
state.fieldBlocFromPath('email').asSelectFieldBloc<T>().value;

The proposal is add method that get the current value of a FieldBloc without access to the FieldBloc before,, reducing the amount of code.

Option 1:

state.fieldBlocValue<T>('path');
state.fieldBlocValue('path');
state.fieldBlocValue<String>('path');
state.fieldBlocValue<DateTime>('path');

Option 2:

state.getFieldBlocValue<T>('path');
state.getFieldBlocValue('path');
state.getFieldBlocValue<String>('path');
state.getFieldBlocValue<DateTime>('path');

Option 3:

state.findFieldBlocValueOf<T>('path');
state.findFieldBlocValueOf('path');
state.findFieldBlocValueOf<String>('path');
state.findFieldBlocValueOf<DateTime>('path');

Option 4: (This will be added in form_bloc 0.10.5)

state.valueOf<T>('path');
state.valueOf('path');
state.valueOf<String>('path');
state.valueOf<DateTime>('path');

The generic type T is for have static analysis.


Do you have any suggestion? maybe other names?

[Proposal] in addFieldBloc and removeFieldBloc methods change named parameters to positional parameters.

Before

  addFieldBloc({@required FieldBloc fieldBloc, String path})

After

  addFieldBloc(FieldBloc fieldBloc, {String path})

Before

  removeFieldBloc({@required String path})

After

  removeFieldBloc(String path)

With this change it is more intuitive and requires less code to add / remove field blocs:

addFieldBloc(TextFieldBloc(name: 'textField'));
addFieldBloc(TextFieldBloc(name: 'textField'), path: 'list/group/list');
removeFieldBloc('textField');
removeFieldBloc('list/group/list/25);

Improve form bloc for CRUD operations

Currently you can use easily form bloc to read and create, but it is not easy not to update or delete.

Update operation:

  • Add isEditing property to the form bloc state,

So if you want the to set isEditing to true in the initial state you set in the super constructor, by default it will be false.
Then you can use in the onSubmitting method for create or update.

Delete operation:

  • Add onDelete method that is called when delete event is added to de bloc.
  • Add new states for manage this event:
    • FormBlocDeleting automatically yielded when call delete.
    • FormBlocDeleteFailed use with state.toDeleteFailed.
    • FormBlocDeleteSuccessful use with state.toDeleteSuccessful.

Example:

import 'package:form_bloc/form_bloc.dart';

class CrudFormBloc extends FormBloc<String, String> {
  final TextFieldBloc nameField;

  CrudFormBloc({String name})
      : nameField = TextFieldBloc(initialValue: name), // Read logic...
        super(isEditing: name != null);

  @override
  List<FieldBloc> get fieldBlocs => [nameField];

  @override
  Stream<FormBlocState<String, String>> onSubmitting() async* {
    if (state.isEditing) {
      try {
        // Update logic...
        yield state.toSuccess();
        yield state.toLoaded();
      } catch (e) {
        yield state.toFailure();
      }
    } else {
      try {
        // Create logic...
        yield state.toSuccess();
        yield state.toLoaded(isEditing: true);
      } catch (e) {
        yield state.toFailure();
      }
    }
  }

  @override
  Stream<FormBlocState<String, String>> onDelete() async* {
    try {
      // Delete Logic...
      yield state.toDeleteSuccessful();
    } catch (e) {
      yield state.toDeleteFailed();
    }
  }
}

Add an example for dynamic fields

Right now I have a system where users can click a button and it adds a new field into the fieldBlocs list and to a separate map in the same file. I was wondering if you could make an official example of how dynamic fields should be implemented since my system is a little janky.

Help with BooleanFieldBloc and SelectFieldBloc

// addFieldBloc(
// fieldBloc: BooleanFieldBloc(
// name: 'boolean',
// validators: FieldBlocValidators.requiredBooleanFieldBloc));

and help me to make a dropdownbloc i am new in flutter

[Bug] Opening drowdown after focus on other field.

When you have a Dropdown,

if you focus another field, when coming back to list will open => close very fast the list and close => open the keyboard giving focus to the field.

Seems to be a bug of https://github.com/adee42/flutter_keyboard_visibility, onChange never fired.

in dropdown_field_bloc_builder.dart, lines 268 - 275, changing:

if (_keyboardVisibility.isKeyboardVisible) {
        //_effectiveFocusNode.requestFocus();
        await Future<void>.delayed(Duration(milliseconds: 1));
        _effectiveFocusNode.unfocus();
        await Future<void>.delayed(Duration(
            milliseconds:
                widget.millisecondsForShowDropdownItemsWhenKeyboardIsOpen));
      }

by

 if (MediaQuery.of(context).viewInsets.bottom != 0) {
        FocusScope.of(context).requestFocus(new FocusNode());
        await Future.delayed(Duration(milliseconds: 1));
      }

solved this bug.
Solution based on comments from the link into your TODO comment. (line 267)

flutter/flutter#18672 (comment)

[Feature request] Add autoSubmit option with debounce time.

Proposal:

Add to the super constructor:

  • autoSubmit : by default false,
  • autoSubmitDebounceTime by default 1000 milliseconds.

when you set autoSubmit to true, submit will be called when any fieldBloc changes its value after the debounce time, so if all fields are valid, then onSubmitting will be called.

class MyFormBloc extends FormBloc<String, String> {
  MyFormBloc()
      : super(
           autoSubmit: true, 
           autoSubmitDebounceTime: Duration(milliseconds: 500),
        ) {
    // Add fields...
  }

  
  @override
  Stream<FormBlocState<String, String>> onSubmitting() async* {
    // Awesome logic...
  }
}

Do you have any suggestion?

Add isRequired parameter to FieldBloc to avoid using FieldBlocValidators.required ... type

Before:

  TextFieldBloc(
    validators: [FieldBlocValidators.requiredTextFieldBloc],
  )

  SelectFieldBloc(
    validators: [FieldBlocValidators.requiredSelectFieldBloc],
  )

After

  TextFieldBloc(
    isRequired: true,
  )

  SelectFieldBloc(
    isRequired: true,
  )
  • isRequired by default is false, and add FieldBlocValidatorsErrors.required like error message.

Also with this change, we can have fields that can have different validators, but that does not imply that it is required, so they will never be invoked if the field is empty and isRequired is false

So the next validators will be removed:

  • FieldBlocValidators.requiredInputFieldBloc
  • FieldBlocValidators.requiredBooleanFieldBloc
  • FieldBlocValidators.requiredTextFieldBloc
  • FieldBlocValidators.requiredSelectFieldBloc
  • FieldBlocValidators.requiredMultiSelectFieldBloc

[Feature request] Add CalculatedFieldBloc

CalculatedFieldBloc would be a FieldBloc that subscribes to others FieldBlocs and applying a function based on the states of the others FieldBlocs to set their value.

Add support for TextField.minLines

TextField.minLines is supported only in TextFieldBlocBuilder but is not passed to TextFieldConfiguration.
However, it is not supported in TypeAheadField and in TextFieldConfiguration
Please add support

Clear text form without getting error message

I am using form_bloc and its working well until i have to clear text from Forms. While i try to clear text using nameField.updateValue("") or nameField.clear() i got error message "this field is required" at that form. How i cleared text without i got error message? sorry for my bad english

Do you follow Semantic Versioning ?

I am using flutter_form_bloc in my flutter project , Today I upgrade it from 0.5.0 to 0.10.2
It seems there is a breaking change

In onSubmitting I used yield state.toSuccess(myString); many times ,after upgrading I have to change it to yield state.toSuccess(successResponse: response);

OnTap is not working

great package to use. I find it very helpful. however, I noticed that onTap functionality doesnt work on TextFieldBlocBuilder. when the text field is click/tap, the code inside onTap doesnt execute. please solve this issue. your package is excellent but without OnTap functionally working it becomes limited to some people

Dropdown..Builder add support for hintText

Is it possible to add support for [InputDecoration.hintText, InputDecoration.labelText] to DropdownFieldBlocBuilder?
Right now. If we set in InputDecoration.hintText with a value the DropdownFieldBlocBuilder will not show the InputDecoration.hintText value. When no value is selected

[Question] Populate Dropdown list from json from api

Is there a way to populate a SelectFieldBloc from the json returned from API. I have a

Future<List<String>> itemsList 

in my Repository class. But I can not assign it to items.

fieldBloc: SelectFieldBloc(
    name: 'circuitId',
    items: Repository.itemsList,
  ),

Using datepicker or year picker

Are we limited to use only textbox , dropdown , checkbox and radio?

https://github.com/GiancarloCode/form_bloc/tree/master/packages/flutter_form_bloc#widgets

I need to have a text box with which should only allow the user to select year between 1970 to 2020 (or current year). Populating the dropdown with all years does not look good.

[Feature request] Add extraData / description property to SingleFieldBloc

What is SingleFieldBloc?
  • InputFieldBloc
  • TextFieldBloc
  • BooleanFieldBloc
  • SelectFieldBloc
  • MultiSelectFieldBloc
  • In some cases, you may want to create dynamic fields based on json / object which you need to get from network request, so regarding user interface, you can't define a label name, image of background, etc.

    You may also want more information on that field when you want to submit the form.

    It would be useful to add a property that allows adding additional data to the SingleFieldBloc, that will be available in its state.


    In the BLoC:

    addFieldBloc(
         TextFieldBloc(
            name: 'item',
            extraData: {
              'id': itemResponse.label,
              'group': itemResponse.group,
              'label': itemResponse.label,
            }
          ),
      path: 'list',
    )

    In the UI:

               FieldBlocListBuilder(
                  fieldBlocList: state.fieldBlocFromPath('list'),
                  itemBuilder: (context, fieldBlocList, index) {
                    final textFieldBloc= fieldBlocList[index].asTextFieldBloc;
                    return TextFieldBlocBuilder(
                      textFieldBloc: textFieldBloc,
                      decoration: InputDecoration(
                        labelText: textFieldBloc.state.extraData['label'],
                      ),
                    );
                  },
                ),

    What type should this property have?

    Option 1:

    dynamic extraData

    Any type... so you need to cast fo static analysis
    example:

    (textFieldBloc.state.extraData as CustomType).label;
    (textFieldBloc.state.extraData as Map<String, dynamic>)['label'];

    Option 2:

    Map<String, dynamic> extraData

    Like a json
    example:

    textFieldBloc.state.extraData['label']

    Option 3:

    CustomType extraData...

    To have static analysis we should add an extra type to the singleFieldBlocs, something that can be annoying.
    for example:

    InputFieldBloc<Value, ExtraData>
    TextFieldBloc<ExtraData>

    What name should this property have?

    Option 1:

    extraData

    Option 2:

    description

    Do you suggest another name? which one?


    [Question] More typings

    Hi. Thanks for the package.
    I'm curious are there any plans to add more types to eliminate the access by random string

    Sample from the example app

    print(state.fieldBlocFromPath('clubName').asTextFieldBloc.value);
        final members = state.fieldBlocFromPath('members').asFieldBlocList.map(
          (memberField) {
            return Member(
              firstName:
                  memberField.asGroupFieldBloc['firstName'].asTextFieldBloc.value,
              lastName:
                  memberField.asGroupFieldBloc['lastName'].asTextFieldBloc.value,
              hobbies: memberField.asGroupFieldBloc['hobbies'].asFieldBlocList
                  .map((hobbyField) => hobbyField.asTextFieldBloc.value)
                  .toList(),
            );
          },
        );
    

    As far as we use ['firstName'] there is no type checking and could be a source of unexpected behaviour.

    Question : override defaultErrorBuilder globaly

    I want to override defaultErrorBuilder to customize error messages globaly , How can I do this?

    I see that each fields accept errorBuilder passed to Style.getErrorText , it is very cumbersome to pass my errorBuilder each time to each fields , How can I do it easily?

    I think we can extend TextFieldBlocBuilder and create new constructor , but I dont know can can I do it in dart in clean way

    Optional field but validation converts it to required

    I can't create an optional and validated field
    For example, I want the user to enter an email but optionally.
    For this I write the following:

    addFieldBloc(fieldBloc: TextFieldBloc(name: 'email', validator: [FieldBlocValidators.email]))

    But this is the verification code of the email:

    static String email(String string) {
        final emailRegExp = RegExp(
          r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
        );
        if (string != null && emailRegExp.hasMatch(string)) {
          return null;
        }
        return FieldBlocValidatorsErrors.email;
      }

    If string is null or empty it will return an error. So the field is 'required' but that's not what I want to achieve
    So the correct code would be:

    static String email(String string) {
        final emailRegExp = RegExp(
          r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
        );
        if (string == null || string.isEmpy || emailRegExp.hasMatch(string)) {
          return null;
        }
        return FieldBlocValidatorsErrors.email;
      }

    PS: In the case instead I want the field to be an email and that it is required I will write then

    addFieldBloc(fieldBloc: TextFieldBloc(name: 'email', validator: [
      FieldBlocValidators.requiredText,  
      FieldBlocValidators.email,
    ]))

    This would create problems if the email is before requiredText but it can be solved by adding isRequired as always proposed in the first position of the list
    What do you think about it? Thanks

    [BUG]? Radio group does not select initial value when map<String, String> is used

    When you add the field as follows:

    addFieldBloc(
      fieldBloc: SelectFieldBloc<Map<String, String>>(
        name: 'bench',
        initialValue: {'key': 'A', 'value': 'All Benches'},
        validators: [FieldBlocValidators.requiredSelectFieldBloc],
        items: [
          {'key': 'A', 'value': 'All Benches'},
          {'key': 'S', 'value': 'Single Bench'},
          {'key': 'D', 'value': 'Division Bench'},
        ],
      ),
    )
    

    and ui code

    RadioButtonGroupFieldBlocBuilder<Map<String, String>>(
                        canDeselect: false,
                        selectFieldBloc: state.fieldBlocFromPath('bench'),
                        itemBuilder:
                            (BuildContext context, Map<String, String> bench) {
                          return bench["value"];
                        },
                      )
    

    I would expect the first radio button to be selected by default. But it is not! Also, the validators do not seem to work too for this field.

    DateTimeFieldBloc initial date is required

    Somehow initialDate is required alongside with firstDate and lastDate

    const DateTimeFieldBlocBuilder({
        Key key,
        @required this.dateTimeFieldBloc,
        @required this.format,
        this.canSelectTime = false,
        this.enableOnlyWhenFormBlocCanSubmit = false,
        this.isEnabled = true,
        this.errorBuilder,
        this.padding,
        this.decoration = const InputDecoration(),
        @required this.initialDate,
        @required this.firstDate,
        @required this.lastDate,
        this.initialTime,
        this.selectableDayPredicate,
        this.locale,
        this.textDirection,
        this.pickerBuilder,
        this.useRootNavigator = false,
        this.routeSettings,
        this.animateWhenCanShow = true,
      })
    

    suggestion menu reappearing after selecting one of the suggesstions

    I was testing the code from the github repository. i tried the complex login screen. when i click on the email textfield, a suggesstion dropdown comes up. when i choose a value, the textfield populates but the dropdown menu comes up again. after the second time selecting the same value, then the suggestion dropdown disappear. see attachment of value selected and menu still appear instead of disappearing

    menu_reappearing

    Android-Emulator-Nexus_5X_API_26_5554-12_15_2019-12_17_12-PM

    How to reset manually added errors using "addError"?

    Using your example for manually adding an error, how do you "reset" the form after you return a failure so that the submission can be attempted again? For example, my login checks for an email verified user and will return an error if unverified. I don't want that state cached client-side as it should be checked every time. I also would rather not send a separate async validation request to the server first. I've tried resetting the initial validators but the form still won't "resend". Thoughts?

      @override
      Stream<FormBlocState<String, String>> onSubmitting() async* {
        yield state.toLoading();
    
        final email = state.fieldBlocFromPath('email').asTextFieldBloc;
        final password = state.fieldBlocFromPath('password').asTextFieldBloc;
    
        try {
          final token = await authBloc.authRepository.authenticate(
            username: email.value.trim().toLowerCase(),
            password: password.value.trim(),
          );
    
          yield state.toLoaded();
          yield state.toSuccess(successResponse: token);
    
          authBloc.add(AuthLoggedIn(token: token));
    
          // Clear fields
          password.clear();
        } on ServerFieldException catch (fieldExceptions) {
          final messages = [];
          for (var exception in fieldExceptions.exceptions) {
            messages.add(exception.message);
            // Add field validator errors
            state
                .fieldBlocFromPath(exception.name)
                .asTextFieldBloc
                .addError(exception.message);
          }
    
          yield state
              .toFailure(messages.reduce((value, acc) => '$value\n'));
    
          // Reset validators
          // email.updateValidators(_validators['email']);
          // password.updateValidators(_validators['password']);
        }
      }

    Adding a field bloc doesn't call listener

    I have a method that adds a FieldBloc to a path called 'teams'. If I were to remove the path parameter, thereby making it null, the state updates and when I print state.fieldBlocs, it returns the correct map but if I specify a path name and I click the button to call the function, nothing happens.

    Here's the method that adds the FieldBloc:

      void addTeamField({String name}) {
        addFieldBloc(
          path: 'teams',
          fieldBloc: TextFieldBloc(
            name: 'teamName',
            initialValue: name ?? '',
            validators: [FieldBlocValidators.requiredTextFieldBloc],
          ),
        );
      }
    

    I try to access it like this:

    print(state.fieldBlocs);
    final fields = state.fieldBlocFromPath('teams')?.asFieldBlocList;
    

    but it always returns null. Why is that?

    Is it because there's only one FieldBloc being added?

    Fix obscure text

    Hi, when i try to use SuffixButton.obscureText in second step of stepper/wizard form, initial state is obscureText false, I must click on suffixButton, then obscureText is true. If i put this password field in first step, everything is ok.

    class LoginFormBloc extends FormBloc<String, String> {
      final TextFieldBloc email = TextFieldBloc(
          validators: [FieldBlocValidators.required, FieldBlocValidators.email]);
      final TextFieldBloc password =
          TextFieldBloc(validators: [FieldBlocValidators.required]);
      LoginFormBloc() {
        addFieldBlocs(step: 0, fieldBlocs: [email]);
        addFieldBlocs(step: 1, fieldBlocs: [password]);
      }
    
    
    StepperFormBlocBuilder<LoginFormBloc>(
                    stepsBuilder: (formBloc) {
                      return [_emailStep(formBloc), _passwordStep(formBloc)];
                    },
                    physics: ClampingScrollPhysics(),
                    type: StepperType.horizontal,
                    formBloc: loginFormBloc,
                  ));
    
    FormBlocStep _passwordStep(LoginFormBloc loginFormBloc) {
      return FormBlocStep(
          title: Text('Password'),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Text('Enter password to sign in with your email'),
              TextFieldBlocBuilder(
                suffixButton: SuffixButton.obscureText,
                decoration: InputDecoration(
                    prefixIcon: Icon(Icons.lock),
                    hintText: 'Password',
                    border: OutlineInputBorder()),
                textFieldBloc: loginFormBloc.password,
              ),
            ],
          ));
    }
    

    DateTimeFieldBloc removes existing value in case of cancel press

    Hi - it's me again)

    If I have prepopulated value in DateTimeFieldBloc -> open the date picker -> press Cancel -> resets prepopulated value to null

    Here is why - the datepicel returns null in case of cancel and you put it directly into the field value

    if (type == DateTimeFieldBlocBuilderBaseType.date) {
                              final date = await _showDatePicker(context);
                              dateTimeFieldBloc.updateValue(date as T);
                            }
    

    FieldBlocs are null on first-time build

    I have this piece of code for a Sign In page

    ...
    
    @override
     Widget build(BuildContext context) {
        return FormBlocListener<SignUpValidationBloc, String, AuthError>(
          formBloc: signUpBloc,
          onLoading: (context, state) => showDialog(
            context: context,
            builder: (context) => Container(
              height: 100,
              width: 100,
              child: Center(
                child: CupertinoActivityIndicator(),
              ),
            ),
          ),
         ...
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.only(
                  top: Styles.kLargePadding,
                  bottom: Styles.kLargePadding,
                ),
                child: _buildFields(_signUpValidationBloc),
              ),
             ...
            ],
          ),
        );
      }
    
    ...
    
    Widget _buildFields(SignUpValidationBloc signUpBloc) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: Styles.kLargePadding),
          child: Column(
            children: <Widget>[
              AuthTextForm(
                hintText: AppLocalizations.of(context).translate("signup_email"),
                action: TextInputAction.next,
                onFieldSubmitted: (_) =>
                    FocusScope.of(context).requestFocus(_passwordNode),
                focusNode: _emailNode,
                type: TextInputType.emailAddress,
                bloc: signUpBloc.state.textFieldBlocOf("email"),
              ),
              SizedBox(
                height: Styles.kSemiLargePadding,
              ),
              AuthTextForm(
                hintText: AppLocalizations.of(context).translate("signup_password"),
                isPassword: true,
                action: TextInputAction.done,
                focusNode: _passwordNode,
                bloc: signUpBloc.state.textFieldBlocOf("password"),
                onFieldSubmitted: (_) => signUpBloc.submit(),
              ),
            ],
          ),
        );
      }

    As you can see, I build two custom TextFields at _buildFIelds method passing their corresponding FieldBloc as an argument (bloc) for each Widget.

    Problem is the textfields do not appear when building for the first time. It looks like the FieldBlocs are null at this point. But if I hot reload, they appear.

    I don't know if I'm doing something wrong but I'm having a hard time figuring out how to solve this.

    [Question] HydratedFromBlock

    Hi. Is there any quick example how to add support of hydrated_bloc to form_bloc?
    Except manual implementation

    [Feature request] Add toJson to FormBlocState

    We currently have a Map <String, FieldBloc> fieldBlocs, It would be great to have also Map<String, dynamic> toJson() method that returns a json based fieldBlocs with the current values of each fieldBloc


    • state.fieldBlocs:
    {
        "clubName": TextFieldBloc(...),
        "members": FieldBlocList([
            GroupFieldBloc(
              {
                  "firstName": TextFieldBloc(...),
                  "lastName": TextFieldBloc(...),
                  "hobbies": FieldBlocList([
                      TextFieldBloc(...),
                      TextFieldBloc(...)
                  ])
              }
            )     
        ])
    }
    • state.toJson:
    {
      "clubName": "Awesome Club",
      "members": [
        {
          "firstName": "John",
          "lastName": "Doe",
          "hobbies": [
            "Computer programming",
            "Animation"
          ]
        }
      ]
    }
    ClubForm extends FormBloc<String, String>{
    ...
      @override
      Stream<FormBlocState<String, String>> onSubmitting() async* {
        final club = Club.fromJson(state.toJson());
        // Awesome logic...
      }
    ...
    }

    Club model (Although in production you could use built_value or json_serialization):

    class Club {
      String clubName;
      List<Members> members;
    
      Club({this.clubName, this.members});
    
      Club.fromJson(Map<String, dynamic> json) {
        clubName = json['clubName'];
        if (json['members'] != null) {
          members = List<Members>();
          json['members'].forEach((v) {
            members.add(Members.fromJson(v));
          });
        }
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = Map<String, dynamic>();
        data['clubName'] = this.clubName;
        if (this.members != null) {
          data['members'] = this.members.map((v) => v.toJson()).toList();
        }
        return data;
      }
    }
    
    class Members {
      String firstName;
      String lastName;
      List<String> hobbies;
    
      Members({this.firstName, this.lastName, this.hobbies});
    
      Members.fromJson(Map<String, dynamic> json) {
        firstName = json['firstName'];
        lastName = json['lastName'];
        hobbies = json['hobbies'].cast<String>();
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = Map<String, dynamic>();
        data['firstName'] = this.firstName;
        data['lastName'] = this.lastName;
        data['hobbies'] = this.hobbies;
        return data;
      }
    }

    Add an example of a field using BlocBuilder/BlocListener

    It would be great if you could add an example (or add on to another example like the 'form_fields_example_form') of you using a FieldBloc such as InputFieldBloc to create a DateTime field or something using BlocBuilder or BlocListener.

    [question] example to access API backend using form_block 0.12.0

    Can somebody give me an example how to access a backend API using the latest 0.12.0 version of form_bloc?
    It needs already be defined in main.dart...and then implemented in the bloc
    I have it working in the bloc, but want it already started in main.dart so it does not restart with every screen.
    Thanks in advance!
    Hans

    sister list_bloc or table_bloc

    Hi! This is a very useful package saving lots of boilerplate.

    I was thinking if something similar should be created for loading / managing list / table data ?

    With load/reload, load more, loading, error, delete, filter and to be combined with the form_bloc for the create/update?

    This will give us the full crud.

    Any ideas about this or any similar package I should know about before giving it a try?

    Recommend Projects

    • React photo React

      A declarative, efficient, and flexible JavaScript library for building user interfaces.

    • Vue.js photo Vue.js

      ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

    • Typescript photo Typescript

      TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

    • TensorFlow photo TensorFlow

      An Open Source Machine Learning Framework for Everyone

    • Django photo Django

      The Web framework for perfectionists with deadlines.

    • D3 photo D3

      Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

    Recommend Topics

    • javascript

      JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

    • web

      Some thing interesting about web. New door for the world.

    • server

      A server is a program made to process requests and deliver data to clients.

    • Machine learning

      Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

    • Game

      Some thing interesting about game, make everyone happy.

    Recommend Org

    • Facebook photo Facebook

      We are working to build community through open source technology. NB: members must have two-factor auth.

    • Microsoft photo Microsoft

      Open source projects and samples from Microsoft.

    • Google photo Google

      Google โค๏ธ Open Source for everyone.

    • D3 photo D3

      Data-Driven Documents codes.