-
- Notifications
You must be signed in to change notification settings - Fork 559
Description
Is there an existing issue for this?
- I have searched the existing issues
Package/Plugin version
9.2.1
Platforms
- Android
- iOS
- Linux
- MacOS
- Web
- Windows
Flutter doctor
Flutter doctor
[√] Flutter (Channel stable, 3.19.6, on Microsoft Windows [Version 10.0.22631.3447], locale en-IN) • Flutter version 3.19.6 on channel stable at C:\src\flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 54e66469a9 (2 weeks ago), 2024-04-17 13:08:03 -0700 • Engine revision c4cd48e186 • Dart version 3.3.4 • DevTools version 2.31.1 [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 33.0.1) • Android SDK at C:\Users\Nipun Shah\AppData\Local\Android\sdk • Platform android-33-ext4, build-tools 33.0.1 • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [X] Visual Studio - develop Windows apps X Visual Studio not installed; this is necessary to develop Windows apps. Download at https://visualstudio.microsoft.com/downloads/. Please install the "Desktop development with C++" workload, including all of its default components [√] Android Studio (version 2022.3) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231) [√] IntelliJ IDEA Community Edition (version 2022.3) • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2022.3.1 • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart [√] VS Code (version 1.87.2) • VS Code at C:\Users\Nipun Shah\AppData\Local\Programs\Microsoft VS Code • Flutter extension can be installed from: https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter [√] Connected device (3 available) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.22631.3447] • Chrome (web) • chrome • web-javascript • Google Chrome 115.0.5790.171 • Edge (web) • edge • web-javascript • Microsoft Edge 124.0.2478.67 [√] Network resources • All expected network resources are available. ! Doctor found issues in 1 category.
Minimal code example
Code sample
import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; void main() { runApp(const MyApp()); } const kCountryItems = ['India', 'US', 'Japan']; const kStateItems = [ 'Gujarat', 'Rajasthan', 'Punjab', 'Florida', 'California', 'Texas', 'Kinki', 'Shikoku', 'Tohoku' ]; class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { String? _country = kCountryItems.first; String? _state = kStateItems.first; // Can be used later to manipulate fields final _formKey = GlobalKey<FormBuilderState>(); @override Widget build(BuildContext context) { const gap = SizedBox(height: 12); return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: Container( width: 300, color: Colors.blue.shade100, padding: const EdgeInsets.all(12), child: FormBuilder( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ const Text('Form'), gap, CountryInput( initialValue: _country, onChanged: _onCountryChanged, ), gap, StateInput( // ? Enforcing state input to reset/recreate asa `_country` changes key: ValueKey(_country), initialValue: _state, onChanged: _onStateChanged, ), gap, ], ), ), ), ), ); } void _onCountryChanged(String? country) { setState(() { _country = country; // ?? Eventhough state is made null & we used ValueKey() for StateInput to force recreation, it will retain old value !! _state = null; print('(: Country Changed > C:- $_country S:- $_state'); }); } void _onStateChanged(String? state) { _state = state; print('(: State Changed > $_state'); } } class CountryInput extends StatelessWidget { const CountryInput({super.key, this.initialValue, required this.onChanged}); static String id = 'country'; final String? initialValue; final ValueChanged<String?> onChanged; @override Widget build(BuildContext context) { return FormBuilderField<String>( name: CountryInput.id, initialValue: initialValue, builder: (field) => _buildField(field), onChanged: onChanged, ); } Widget _buildField(FormFieldState<String> field) { return DropdownMenu( width: 250, initialSelection: field.value, onSelected: (value) { field.didChange(value); }, dropdownMenuEntries: kCountryItems .map((e) => DropdownMenuEntry<String>(value: e, label: e)) .toList()); } } class StateInput extends StatelessWidget { const StateInput({super.key, this.initialValue, required this.onChanged}); static String id = 'state'; final String? initialValue; final ValueChanged<String?> onChanged; @override Widget build(BuildContext context) { return FormBuilderField<String>( name: StateInput.id, initialValue: initialValue, builder: (field) => _buildField(field), onChanged: onChanged, ); } Widget _buildField(FormFieldState<String> field) { return DropdownMenu( width: 250, initialSelection: field.value, onSelected: (value) { field.didChange(value); }, dropdownMenuEntries: kStateItems .map((e) => DropdownMenuEntry<String>(value: e, label: e)) .toList()); } }
Current Behavior
FormBuilderField : widget whenever coerced/forced to be recreated (ie maybe via ValueKey or UniqueKey), it's retaining the previous field's value.
Given that
name
parameter remains unchanged before & after forced recreation
In above code example
- The initial value for
CountryInput = India
&StateInput = Gujarat
- StateInput retains value = Gujarat even when CountryInput is changed
NOTE: here StateInput holds
key = ValueKey(_country), hence it will be recreated.
Expected Behavior
FormBuilderField : widget whenever coerced/forced to be recreated (ie maybe via ValueKey or UniqueKey), it should respect & attain the latest field's initial value rather than prioritizing the previous (stale) field's value,
Given that latest field's
name
= old field'sname
.
In above code example
- The initial value for
CountryInput = India
&StateInput = Gujarat
- Whenever CountryInput is changed, StateInput must reset & hence no selected value (ie
_state = null
)
i.eCountryInput = 'Japan'
&StateInput = ''
NOTE: here StateInput holds
key = ValueKey(_country)
, hence it will be recreated; thus current value of_state
(i.e null) should be considered as an initial value for the latest StateInput field.
Steps To Reproduce
- Provide some initial value to your
FormBuilderField
(let say initialValue = 'Gujarat') - Try to change value of initialVal variable holder to null
- Try to forcefully recreate your
FormBuilderField
widget or any of it's ancestor. (for an instance, you can use UniqueKey)
[With above sample code]
- create flutter project
- add dependency ->
flutter_form_builder: ^9.2.1
don't forget to do
flutter pub get
- copy paste aforementioned sample code into main.dart
- run the project
Initially selected value => Country = India & State = Gujarat
- Try to change the country by tapping CountryInput DropDownMenu
You will observe that StateInput still holds Gujarat.
Aditional information
Below is my console snippet when I followed above steps to reproduce
(: Country Changed > C:- US S:- null Warning! Replacing duplicate Field for state -- this is OK to ignore as long as the field was intentionally replaced Warning! Ignoring Field unregistration for state -- this is OK to ignore as long as the field was intentionally replaced