felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.69k stars 3.38k forks source link

feat: Create a mutable object starting from the state of a bloc. #4209

Open MattiaPispisa opened 1 month ago

MattiaPispisa commented 1 month ago

Description

A use case I encounter in some situations (especially when creating complex forms) is having an object that changes over time but should not reside in the bloc state. For example, I have a TextFormField that require using a TextEditingController because their content can change due to actions outside the field itself. Recreating the TextEditingController would necessitate repositioning the cursor correctly and dealing with other issues.

A concrete example: I have a bloc BlocA that manages the insertion and modification of a field T. In the UI, I have a TextFormField where I need to enter the field T, and with each change, a change event is triggered to BlocA. In addition to this field, to speed up the user experience, a QR code scanner can be used. So, values can be scanned using the camera. Upon scanning a value, a modification event is triggered to BlocA. Of course, the TextFormField must update with the new value obtained from the scan. And in any case, whether the insertion is through a QR code scan or because the user has modified a part of the content (not necessarily the end), the TextEditingController cursor must be positioned correctly.

Desired Solution

The idea is to create a widget similar to BlocSelector. Essentially, it involves listening to the state changes of the bloc, but in this case, to create and subsequently mutate an object (MutableState) looking at the previous.MutableState and the current bloc state. This object will then be passed as a parameter in the builder method to compose the child widget.

https://github.com/felangel/bloc/pull/4207

Alternatives Considered

Taking as an example the use of a TextFormField with a TextEditingController, the alternative solutions I have considered are:

felangel commented 1 month ago

Hi @MattiaPispisa 👋 Thanks for opening an issue!

Can you share a minimal reproduction sample to illustrate the problem? Also, have you taken a look at some of the form validation examples? (https://github.com/felangel/bloc/blob/master/examples/flutter_form_validation/lib/main.dart)

MattiaPispisa commented 1 month ago

Yes, I am familiar with the examples, but unfortunately, they not address my specific case: the value of the TextFormField being modified by another field. This problem could also occur when needing to use ValueNotifier or other entities that have an internal state to update, rather than recreating them every time.

Starting from the example you linked, I will create a sample to illustrate my need.

felangel commented 1 month ago

Yes, I am familiar with the examples, but unfortunately, they not address my specific case: the value of the TextFormField being modified by another field. This problem could also occur when needing to use ValueNotifier or other entities that have an internal state to update, rather than recreating them every time.

Starting from the example you linked, I will create a sample to illustrate my need.

Thanks! Having a concrete example to look at would be super helpful 👍

MattiaPispisa commented 1 month ago

Here I am :) !

My concrete example

This idea originated from this problem, and it can apply to various cases (like for ValueNotifier).

The example is very similar to the linked one, but here there is only one text field for the client, which can also be modified by external actions like the button below (imagine it as the QR code reader I mentioned before).

ClientInput is the equivalent input similar to those in the sample, with the issue that it won't update when the button is pressed. ClientInputV2 represents one of the "Alternatives Considered" that I included in this issue, but here the problem shifts to managing the input cursor, try changing some characters in the middle of the input (Instead of the controller, using a key in the widget can also be considered, but the problem remains the same).