flutter-form-builder-ecosystem / flutter_form_builder

Simple form maker for Flutter Framework
https://pub.dev/packages/flutter_form_builder
MIT License
1.48k stars 535 forks source link

FormBuilderTextField sets field state to '' even though transformer sets return to null #1350

Closed john-rager closed 8 hours ago

john-rager commented 8 months ago

Is there an existing issue for this?

Package/Plugin version

9.1.1

Platforms

Flutter doctor

Flutter doctor ``` Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.16.3, on Microsoft Windows [Version 10.0.22621.3007], locale en-US) [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 31.0.0) [√] Chrome - develop for the web [√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.5.3) [√] Android Studio (version 2021.2) [√] VS Code (version 1.85.1) [√] Connected device (3 available) [√] Network resources • No issues found! ```

Minimal code example

Code sample ```dart FormBuilderTextField( name: 'writeSize', decoration: const InputDecoration( labelText: 'Write Size (bytes)', ), initialValue: writeSize.toString(), validator: FormBuilderValidators.compose( [ FormBuilderValidators.integer(), FormBuilderValidators.min(1), FormBuilderValidators.max(128), ], ), valueTransformer: (value) => int.tryParse(value!), ), ```

Current Behavior

Trying to use FormBuilderTextField to create a field that accepts either an integer or nothing. The int.tryParse call inside valueTransformer returns null if value is an empty string, however the field state gets set to an empty string rather than null. This forces me to transform the transform so that I can get to the needed null.

While experimenting I took the int.tryParse out of the equation by transforming to null no matter what, e.g. valueTransformer: (value) => null. The field state is still changed to ''.

Expected Behavior

If I am intentionally transforming the value to null, I expect the field state to be null and not an empty string. Am I missing a necessary property?

Steps To Reproduce

Incorporate the above field widget sample into a form and try it out.

Aditional information

I know I can work around this by transforming all of the empty integer fields to null on submit, but this should be unnecessary. Please let me know if this can be fixed or if I'm missing something.

john-rager commented 8 months ago

I've dug into this further and it appears that if the field started out as null and was left null, it works as expected on save - I get a null value and not an empty string. However, if the field is "touched", e.g. I empty a field that has a value or I enter some data and then empty it, the valueTransformer runs and sets the value to null but the currentState.values entry for the field gets set to an empty string at some point between valueTransformer and saveAndValidate.

novaware-io commented 4 months ago

same issue for me, and it makes my serialiser fails: even if the transformer correctly returns null, it still gets saved as '', from a quick check I think it take the null as a return value for "do not transform" and it applies the current value, I think this is wrong in terms of logic as it doesn't work with the nullable fields

marco-origam commented 4 months ago

Im having the same issue, also i pointed it out on the discussions:

https://github.com/flutter-form-builder-ecosystem/flutter_form_builder/discussions/1286

BrottarBasse commented 2 weeks ago

I have looked through the code and the issue is indeed with how the valueTransformer is implemented. As i am not too familiar with the library and there seem to be some dead code in regards to the valueTransformer I am reluctant to make a pull request but could do so if noone else has the time to look through this. The problem is in every instance where the transformer is used:

_transformers[key]?.call(value) ?? value))

This works fine as long as the transformer doesn't transform the value to null. If the transformer however transform the value to null the evaluation will use the original value instead

To fix this changing the above code to:

_transformers[key] == null ? value : _transformers[key]!(value)

Here the transformed value will be used even if it transforms the value to null.