From 1ea0726793eb0b74d6e982b9a1fec7152d696b17 Mon Sep 17 00:00:00 2001 From: Matias de Andrea Date: Sun, 7 May 2023 01:25:17 +0200 Subject: [PATCH 1/2] fix: improve dropdown field - Fix assert error - Replace dropdown widget --- lib/src/fields/form_builder_dropdown.dart | 82 +++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/lib/src/fields/form_builder_dropdown.dart b/lib/src/fields/form_builder_dropdown.dart index 123de05b6..02177d426 100644 --- a/lib/src/fields/form_builder_dropdown.dart +++ b/lib/src/fields/form_builder_dropdown.dart @@ -254,47 +254,39 @@ class FormBuilderDropdown extends FormBuilderFieldDecoration { builder: (FormFieldState field) { final state = field as _FormBuilderDropdownState; - void changeValue(T? value) { - state.didChange(value); - } - - return InputDecorator( + final hasValue = items.map((e) => e.value).contains(field.value); + return DropdownButtonFormField( + isExpanded: isExpanded, decoration: state.decoration, - isEmpty: state.value == null, - child: DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: isExpanded, - items: items, - value: field.value, - style: style, - isDense: isDense, - disabledHint: field.value != null - ? (items - .firstWhereOrNull((dropDownItem) => - dropDownItem.value == field.value) - ?.child ?? - Text(field.value.toString())) - : disabledHint, - elevation: elevation, - iconSize: iconSize, - icon: icon, - iconDisabledColor: iconDisabledColor, - iconEnabledColor: iconEnabledColor, - onChanged: - state.enabled ? (value) => changeValue(value) : null, - onTap: onTap, - focusNode: state.effectiveFocusNode, - autofocus: autofocus, - dropdownColor: dropdownColor, - focusColor: focusColor, - itemHeight: itemHeight, - selectedItemBuilder: selectedItemBuilder, - menuMaxHeight: menuMaxHeight, - borderRadius: borderRadius, - enableFeedback: enableFeedback, - alignment: alignment, - ), - ), + items: items, + value: hasValue ? field.value : null, + style: style, + isDense: isDense, + disabledHint: field.value != null + ? (items + .firstWhereOrNull((dropDownItem) => + dropDownItem.value == field.value) + ?.child ?? + Text(field.value.toString())) + : disabledHint, + elevation: elevation, + iconSize: iconSize, + icon: icon, + iconDisabledColor: iconDisabledColor, + iconEnabledColor: iconEnabledColor, + onChanged: + state.enabled ? (T? value) => state.didChange(value) : null, + onTap: onTap, + focusNode: state.effectiveFocusNode, + autofocus: autofocus, + dropdownColor: dropdownColor, + focusColor: focusColor, + itemHeight: itemHeight, + selectedItemBuilder: selectedItemBuilder, + menuMaxHeight: menuMaxHeight, + borderRadius: borderRadius, + enableFeedback: enableFeedback, + alignment: alignment, ); }, ); @@ -305,4 +297,12 @@ class FormBuilderDropdown extends FormBuilderFieldDecoration { } class _FormBuilderDropdownState - extends FormBuilderFieldDecorationState, T> {} + extends FormBuilderFieldDecorationState, T> { + @override + void didUpdateWidget(covariant FormBuilderDropdown oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.items != oldWidget.items) { + setValue(initialValue); + } + } +} From f7965e0437b4e477a562072ad53f04736d536cf6 Mon Sep 17 00:00:00 2001 From: Matias de Andrea Date: Sun, 7 May 2023 01:25:28 +0200 Subject: [PATCH 2/2] feat: create related fields example --- example/lib/main.dart | 18 ++++ example/lib/sources/related_fields.dart | 110 ++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 example/lib/sources/related_fields.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 522d2e26b..7abd2057d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,6 @@ import 'package:example/sources/conditional_fields.dart'; import 'package:example/sources/dynamic_fields.dart'; +import 'package:example/sources/related_fields.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; @@ -123,6 +124,23 @@ class _HomePage extends StatelessWidget { ); }, ), + const Divider(), + ListTile( + title: const Text('Related Fields'), + trailing: const Icon(Icons.arrow_right_sharp), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) { + return const CodePage( + title: 'Related Fields', + child: RelatedFields(), + ); + }, + ), + ); + }, + ), ], ), ); diff --git a/example/lib/sources/related_fields.dart b/example/lib/sources/related_fields.dart new file mode 100644 index 000000000..de982054c --- /dev/null +++ b/example/lib/sources/related_fields.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; + +class RelatedFields extends StatefulWidget { + const RelatedFields({Key? key}) : super(key: key); + + @override + State createState() => _RelatedFieldsState(); +} + +class _RelatedFieldsState extends State { + final _formKey = GlobalKey(); + String country = ''; + String city = ''; + List cities = []; + + @override + void initState() { + country = _allCountries.first; + city = _allUsaCities.first; + cities = _allUsaCities; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FormBuilder( + key: _formKey, + child: Column( + children: [ + const SizedBox(height: 20), + FormBuilderDropdown( + name: 'country', + decoration: const InputDecoration( + label: Text('Countries'), + ), + initialValue: country, + onChanged: (value) { + setState(() { + country = value ?? ''; + city = ''; + changeCities(); + }); + }, + items: _allCountries + .map((e) => DropdownMenuItem( + value: e, + child: Text(e), + )) + .toList(), + ), + const SizedBox(height: 10), + FormBuilderDropdown( + name: 'city', + decoration: const InputDecoration( + label: Text('Cities'), + ), + initialValue: city, + items: cities + .map((e) => DropdownMenuItem( + value: e, + child: Text(e), + )) + .toList(), + ), + const SizedBox(height: 10), + MaterialButton( + color: Theme.of(context).colorScheme.secondary, + child: const Text( + "Submit", + style: TextStyle(color: Colors.white), + ), + onPressed: () { + _formKey.currentState!.saveAndValidate(); + debugPrint(_formKey.currentState?.instantValue.toString() ?? ''); + }, + ), + ], + ), + ); + } + + void changeCities() { + switch (country) { + case 'France': + cities = _allFranceCities; + break; + case 'United States': + cities = _allUsaCities; + break; + default: + cities = []; + } + } +} + +const _allCountries = [ + 'United States', + 'France', +]; + +const _allUsaCities = [ + 'California', + 'Another city', +]; + +const _allFranceCities = [ + 'Paris', + 'Another city', +];