Skip to content

Commit 6f6b567

Browse files
Merge pull request #1451 from flutter-form-builder-ecosystem/bugfix/1434-initial-value-state
fix: #1434 Replace dropdown
2 parents 1c9acc8 + be613d1 commit 6f6b567

File tree

2 files changed

+105
-31
lines changed

2 files changed

+105
-31
lines changed

lib/src/fields/form_builder_dropdown.dart

+64-31
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
163163
/// [kMinInteractiveDimension].
164164
final double? itemHeight;
165165

166+
/// The width of the menu.
167+
///
168+
/// If it is not provided, the width of the menu is the width of the
169+
/// dropdown button.
170+
final double? menuWidth;
171+
166172
/// The color for the button's [Material] when it has the input focus.
167173
final Color? focusColor;
168174

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

184+
/// Padding around the visible portion of the dropdown widget.
185+
///
186+
/// As the padding increases, the size of the [DropdownButton] will also
187+
/// increase. The padding is included in the clickable area of the dropdown
188+
/// widget, so this can make the widget easier to click.
189+
///
190+
/// Padding can be useful when used with a custom border. The clickable
191+
/// area will stay flush with the border, as opposed to an external [Padding]
192+
/// widget which will leave a non-clickable gap.
193+
final EdgeInsetsGeometry? padding;
194+
178195
/// The maximum height of the menu.
179196
///
180197
/// The maximum height of the menu must be at least one row shorter than
@@ -227,6 +244,11 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
227244
/// this widget is used as the placeholder.
228245
final Widget? hint;
229246

247+
/// The widget to use for drawing the drop-down button's underline.
248+
///
249+
/// Defaults to SizedBox.shrink().
250+
final Widget? underline;
251+
230252
/// Creates field for Dropdown button
231253
FormBuilderDropdown({
232254
super.key,
@@ -263,43 +285,54 @@ class FormBuilderDropdown<T> extends FormBuilderFieldDecoration<T> {
263285
this.borderRadius,
264286
this.alignment = AlignmentDirectional.centerStart,
265287
this.hint,
288+
this.underline = const SizedBox.shrink(),
289+
this.padding,
290+
this.menuWidth,
266291
}) : super(
267292
builder: (FormFieldState<T?> field) {
268293
final state = field as _FormBuilderDropdownState<T>;
269294

270295
final hasValue = items.map((e) => e.value).contains(field.value);
271-
return DropdownButtonFormField<T>(
272-
isExpanded: isExpanded,
296+
return InputDecorator(
273297
decoration: state.decoration,
274-
items: items,
275-
value: hasValue ? field.value : null,
276-
style: style,
277-
isDense: isDense,
278-
disabledHint: hasValue
279-
? items
280-
.firstWhere(
281-
(dropDownItem) => dropDownItem.value == field.value)
282-
.child
283-
: disabledHint,
284-
elevation: elevation,
285-
iconSize: iconSize,
286-
icon: icon,
287-
iconDisabledColor: iconDisabledColor,
288-
iconEnabledColor: iconEnabledColor,
289-
onChanged:
290-
state.enabled ? (T? value) => state.didChange(value) : null,
291-
onTap: onTap,
292-
focusNode: state.effectiveFocusNode,
293-
autofocus: autofocus,
294-
dropdownColor: dropdownColor,
295-
focusColor: focusColor,
296-
itemHeight: itemHeight,
297-
selectedItemBuilder: selectedItemBuilder,
298-
menuMaxHeight: menuMaxHeight,
299-
borderRadius: borderRadius,
300-
enableFeedback: enableFeedback,
301-
alignment: alignment,
302-
hint: hint,
298+
child: DropdownButton<T>(
299+
menuWidth: menuWidth,
300+
padding: padding,
301+
underline: underline,
302+
isExpanded: isExpanded,
303+
items: items,
304+
value: hasValue ? field.value : null,
305+
style: style,
306+
isDense: isDense,
307+
disabledHint: hasValue
308+
? items
309+
.firstWhere(
310+
(dropDownItem) => dropDownItem.value == field.value)
311+
.child
312+
: disabledHint,
313+
elevation: elevation,
314+
iconSize: iconSize,
315+
icon: icon,
316+
iconDisabledColor: iconDisabledColor,
317+
iconEnabledColor: iconEnabledColor,
318+
onChanged: state.enabled
319+
? (T? value) {
320+
field.didChange(value);
321+
}
322+
: null,
323+
onTap: onTap,
324+
focusNode: state.effectiveFocusNode,
325+
autofocus: autofocus,
326+
dropdownColor: dropdownColor,
327+
focusColor: focusColor,
328+
itemHeight: itemHeight,
329+
selectedItemBuilder: selectedItemBuilder,
330+
menuMaxHeight: menuMaxHeight,
331+
borderRadius: borderRadius,
332+
enableFeedback: enableFeedback,
333+
alignment: alignment,
334+
hint: hint,
335+
),
303336
);
304337
},
305338
);

test/src/fields/form_builder_dropdown_test.dart

+41
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,47 @@ void main() {
225225
expect(formValue(widgetName), equals(2));
226226
});
227227
});
228+
testWidgets('Should reset to null when call reset', (tester) async {
229+
const widgetName = 'dropdown_field';
230+
231+
// Define the initial and updated items for the dropdown
232+
const List<DropdownMenuItem<int>> initialItems = [
233+
DropdownMenuItem(value: 1, child: Text('Option 1')),
234+
DropdownMenuItem(value: 2, child: Text('Option 2')),
235+
];
236+
237+
final testWidget =
238+
FormBuilderDropdown(name: widgetName, items: initialItems);
239+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
240+
241+
formKey.currentState?.patchValue({widgetName: 1});
242+
await tester.pumpAndSettle();
243+
formKey.currentState?.reset();
244+
245+
expect(formKey.currentState?.instantValue, {widgetName: null});
246+
});
247+
testWidgets('Should reset to initial when call reset', (tester) async {
248+
const widgetName = 'dropdown_field';
249+
const initialValue = {widgetName: 1};
250+
251+
// Define the initial and updated items for the dropdown
252+
const List<DropdownMenuItem<int>> initialItems = [
253+
DropdownMenuItem(value: 1, child: Text('Option 1')),
254+
DropdownMenuItem(value: 2, child: Text('Option 2')),
255+
];
256+
final testWidget =
257+
FormBuilderDropdown(name: widgetName, items: initialItems);
258+
await tester.pumpWidget(buildTestableFieldWidget(
259+
testWidget,
260+
initialValue: initialValue,
261+
));
262+
263+
formKey.currentState?.patchValue({widgetName: 2});
264+
await tester.pumpAndSettle();
265+
formKey.currentState?.reset();
266+
267+
expect(formKey.currentState?.instantValue, equals(initialValue));
268+
});
228269
}
229270

230271
class MyTestWidget<T> extends StatefulWidget {

0 commit comments

Comments
 (0)