Skip to content

Commit

Permalink
Merge pull request #1451 from flutter-form-builder-ecosystem/bugfix/1…
Browse files Browse the repository at this point in the history
…434-initial-value-state

fix: #1434 Replace dropdown
  • Loading branch information
deandreamatias authored Dec 26, 2024
2 parents 1c9acc8 + be613d1 commit 6f6b567
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 31 deletions.
95 changes: 64 additions & 31 deletions lib/src/fields/form_builder_dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
/// [kMinInteractiveDimension].
final double? itemHeight;

/// The width of the menu.
///
/// If it is not provided, the width of the menu is the width of the
/// dropdown button.
final double? menuWidth;

/// The color for the button's [Material] when it has the input focus.
final Color? focusColor;

Expand All @@ -175,6 +181,17 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
/// instead.
final Color? dropdownColor;

/// Padding around the visible portion of the dropdown widget.
///
/// As the padding increases, the size of the [DropdownButton] will also
/// increase. The padding is included in the clickable area of the dropdown
/// widget, so this can make the widget easier to click.
///
/// Padding can be useful when used with a custom border. The clickable
/// area will stay flush with the border, as opposed to an external [Padding]
/// widget which will leave a non-clickable gap.
final EdgeInsetsGeometry? padding;

/// The maximum height of the menu.
///
/// The maximum height of the menu must be at least one row shorter than
Expand Down Expand Up @@ -227,6 +244,11 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
/// this widget is used as the placeholder.
final Widget? hint;

/// The widget to use for drawing the drop-down button's underline.
///
/// Defaults to SizedBox.shrink().
final Widget? underline;

/// Creates field for Dropdown button
FormBuilderDropdown({
super.key,
Expand Down Expand Up @@ -263,43 +285,54 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
this.borderRadius,
this.alignment = AlignmentDirectional.centerStart,
this.hint,
this.underline = const SizedBox.shrink(),
this.padding,
this.menuWidth,
}) : super(
builder: (FormFieldState<T?> field) {
final state = field as _FormBuilderDropdownState<T>;

final hasValue = items.map((e) => e.value).contains(field.value);
return DropdownButtonFormField<T>(
isExpanded: isExpanded,
return InputDecorator(
decoration: state.decoration,
items: items,
value: hasValue ? field.value : null,
style: style,
isDense: isDense,
disabledHint: hasValue
? items
.firstWhere(
(dropDownItem) => dropDownItem.value == field.value)
.child
: 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,
hint: hint,
child: DropdownButton<T>(
menuWidth: menuWidth,
padding: padding,
underline: underline,
isExpanded: isExpanded,
items: items,
value: hasValue ? field.value : null,
style: style,
isDense: isDense,
disabledHint: hasValue
? items
.firstWhere(
(dropDownItem) => dropDownItem.value == field.value)
.child
: disabledHint,
elevation: elevation,
iconSize: iconSize,
icon: icon,
iconDisabledColor: iconDisabledColor,
iconEnabledColor: iconEnabledColor,
onChanged: state.enabled
? (T? value) {
field.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,
hint: hint,
),
);
},
);
Expand Down
41 changes: 41 additions & 0 deletions test/src/fields/form_builder_dropdown_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,47 @@ void main() {
expect(formValue(widgetName), equals(2));
});
});
testWidgets('Should reset to null when call reset', (tester) async {
const widgetName = 'dropdown_field';

// Define the initial and updated items for the dropdown
const List<DropdownMenuItem<int>> initialItems = [
DropdownMenuItem(value: 1, child: Text('Option 1')),
DropdownMenuItem(value: 2, child: Text('Option 2')),
];

final testWidget =
FormBuilderDropdown(name: widgetName, items: initialItems);
await tester.pumpWidget(buildTestableFieldWidget(testWidget));

formKey.currentState?.patchValue({widgetName: 1});
await tester.pumpAndSettle();
formKey.currentState?.reset();

expect(formKey.currentState?.instantValue, {widgetName: null});
});
testWidgets('Should reset to initial when call reset', (tester) async {
const widgetName = 'dropdown_field';
const initialValue = {widgetName: 1};

// Define the initial and updated items for the dropdown
const List<DropdownMenuItem<int>> initialItems = [
DropdownMenuItem(value: 1, child: Text('Option 1')),
DropdownMenuItem(value: 2, child: Text('Option 2')),
];
final testWidget =
FormBuilderDropdown(name: widgetName, items: initialItems);
await tester.pumpWidget(buildTestableFieldWidget(
testWidget,
initialValue: initialValue,
));

formKey.currentState?.patchValue({widgetName: 2});
await tester.pumpAndSettle();
formKey.currentState?.reset();

expect(formKey.currentState?.instantValue, equals(initialValue));
});
}

class MyTestWidget<T> extends StatefulWidget {
Expand Down

0 comments on commit 6f6b567

Please sign in to comment.