Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: Nesting a dynamic list of cubits inside a bloc (e.g. in a form with dynamic entries) #3969

Closed
WieFel opened this issue Oct 6, 2023 · 2 comments
Labels
question Further information is requested

Comments

@WieFel
Copy link

WieFel commented Oct 6, 2023

Hi,

I am having a use case which is actually not so complex, but I am doubting on how to properly implement it using Bloc (and the formz package). I already opened an issue in the formz package (VeryGoodOpenSource/formz#110), but I think this might be even more related to Bloc itself. I set up a simplified example repository, which can be found here: https://github.com/WieFel/person_form_bloc

Let's assume the following:
We want an app that enables us to create a list of people (Persons) which have a name, age and role (child, adult, senior).

Person form (can be found here)

First of all we create a person form to handle the logic of inputting the data of one person.
Person
The fields have some dependencies between each other: e.g. the role child can only be chosen if age < 18 etc. For implementing that validation logic, we wrap the form inside a PersonFormCubit. In its state (PersonFormState), it holds the 3 fields (FormzInputs using the formz package, but this actually doesn't matter) and an isValid flag which indicates whether the form is valid.

Until here, everything works fine. But now we want to take it one step further:

Event attendee list

We want to have a form in which we can dynamically add Person entries, e.g. an attendee list for an event we are hosting.
Untitled-2022-10-25-1855(6)
We have a button for adding new attendees to the event. The state is held as a list of PersonFormState in the EventAttendeeState (see here).
The EventAttendeeBloc reacts to the adding/editing/deleting of persons in the list.

The list is implemented here as follows (simplified):

BlocBuilder<EventAttendeeBloc, EventAttendeeState>(
  builder: (context, state) {
    return Column(
      children: [
        Expanded(
          child: ListView.builder(
            itemCount: state.attendees.length,
            itemBuilder: (context, index) => BlocProvider<PersonFormCubit>(
            // here we create the wrapping cubit for each person list entry
              create: (context) => PersonFormCubit(state.attendees[index]),
              child: PersonForm(
                onChanged: (newAttendee) {
                  context
                      .read<EventAttendeeBloc>()
                      .add(EventAttendeeChanged(index, newAttendee));
                },
                onDelete: () {
                  context.read<EventAttendeeBloc>().add(EventAttendeeDeleted(index));
                },
              ),
            ),
          ),
        ),
        ElevatedButton(
          onPressed: state.isValid ? () => print('SAVED!') : null,
          child: const Text('Save'),
        ),
      ],
    );
  },
)

Questions

  1. First of all, we are not completely sure whether it is fine to hold a List<PersonFormState> attendees in the EventAttendeeState, or what could be possible alternatives to that approach!?
  2. We have the problem that removing persons from the list doesn't work properly with this implementation.
    E.g. if we have added 3 persons to the list (Person 1, Person 2, Person 3) and remove the "middle" Person 2, the internal state is updated properly, but the UI is displaying the wrong state (it wrongly displays Persons 1 and 2, instead of 1 and 3). This is probably because the BlocProvider<PersonFormCubit>s create function is not executed again. Trying to force a re-creation of the subtree by adding a key to the BlocProvider<PersonFormCubit> only brings other side effects, e.g. that the form fields lose focus on every character input, because the form is re-created on every character input. What would be the suggested way to handle such a case of nesting a dynamic list of cubits, inside another bloc?
@felangel felangel added the question Further information is requested label Oct 27, 2023
@tenhobi
Copy link
Collaborator

tenhobi commented Nov 2, 2023

Hi, regarding question 2, what type of Key did you try to use?

@tenhobi tenhobi added the waiting for response Waiting for follow up label Nov 13, 2023
@felangel
Copy link
Owner

Closing for now since there aren't any actionable next steps. If this is still an issue feel free to respond to @tenhobi and we're happy to continue the conversation 👍

@felangel felangel removed the waiting for response Waiting for follow up label Dec 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants