-
Notifications
You must be signed in to change notification settings - Fork 94
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
Add create accessor factory constructor #283
base: develop
Are you sure you want to change the base?
Conversation
@Husssam12 sounds reasonable. Maybe the doubling of |
make create return generic accessor wrapper
Thanks for replying, I made it more generic |
Hi @Husssam12, Thanks a lot for the issue and for supporting Reactive Forms. This is quite interesting, and an attractive idea. But I have some questions. First, why would you create an inline ControlValueAccesor instead of a separate class with single responsibility in another file (separated from the widget file)? In your example, you have the prettyDuration method that is supposed to be implemented in the same Widget class. Why not create a separated class with this single responsibility (i.e. the value accessor)? I mean, don't make me wrong. I think it is an exemplary implementation of inline ControlValueAccessor, but I would like to understand an actual use case that a separated class doesn't solve. As you may know, adding this feature implies more code to the package to maintain and more tests to add, so I want to make sure it is because of a good reason and that solves a real use case. looking forward to hearing from you. |
The first reason is that I am a bit lazy 😿 , but actually I have two reasons:
So I think it's a slightly faster way to create ControlValueAccessor with less code. I hope I have clarified my use case. |
Hi @Husssam12 What about the "viewToModel" method? In your example you are defining a callback for the "modelToView", but you have not defined one for the "viewToModel": ControlValueAccessor<Duration, String>.create(
modelToView: (modelValue) => prettyDuration(modelValue!),
) Don't you suppose to update the FormControl value from the Widget (the View) value? Thanks in advance. |
Hi again @Husssam12, In your example (use case) you are calling the method prettyDuration() from the duration package passing as an argument the modelValue, but you are not checking if the modelValue is null or not. ControlValueAccessor<Duration, String>.create(
modelToView: (modelValue) => prettyDuration(modelValue!),
) Because the argument of the _ModelToViewValueCallback is a nullable type you should not trust you will receive a not null argument. A safe implementation would be: ControlValueAccessor<Duration, String>.create(
modelToView: (modelValue) => modelValue != null ? prettyDuration(modelValue) : '',
) |
Sorry for the late reply |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## develop #283 +/- ##
===========================================
- Coverage 95.88% 95.59% -0.30%
===========================================
Files 69 63 -6
Lines 1338 1406 +68
===========================================
+ Hits 1283 1344 +61
- Misses 55 62 +7
☔ View full report in Codecov by Sentry. |
Let me recap: at this point we have something like this: typedef ModelToViewCallback<ModelDataType, ViewDataType> = ViewDataType?
Function(ModelDataType? modelValue);
typedef ViewToModelCallback<ModelDataType, ViewDataType> = ModelDataType?
Function(ViewDataType? modelValue);
class InlineValueAccessor<ModelDataType, ViewDataType>
extends ControlValueAccessor<ModelDataType, ViewDataType> {
final ModelToViewCallback<ModelDataType, ViewDataType> _modelToView;
final ViewToModelCallback<ModelDataType, ViewDataType> _viewToModel;
InlineValueAccessor({
required ModelToViewCallback<ModelDataType, ViewDataType> modelToView,
required ViewToModelCallback<ModelDataType, ViewDataType> viewToModel,
}) : _modelToView = modelToView,
_viewToModel = viewToModel;
@override
ViewDataType? modelToViewValue(ModelDataType? modelValue) =>
_modelToView(modelValue);
@override
ModelDataType? viewToModelValue(ViewDataType? viewValue) =>
_viewToModel(viewValue);
} And @mr7ssam based on your use case you will use it like this: ReactiveTextField<Duration>(
valueAccessor: InlineValueAccessor<Duration, String>(
modelToView: (modelValue) => prettyDuration(modelValue!),
viewToModel(viewValue) => null,
),
readOnly: true,
formControl: provider.controls.duration,
), Do you still think it is better than the following solution? ReactiveTextField<Duration>(
readOnly: true,
valueAccessor: DurationValueAccessor(),
formControl: provider.controls.duration,
) class DurationValueAccessor extends ControlValueAccessor<Duration, String> {
@override
String? modelToViewValue(Duration modelValue) => prettyDuration(modelValue!);
@override
Duration? viewToModelValue(String viewValue) => null;
} looking forward to hearing from you. |
Use case in code: