Unverified Commit 92a335e4 authored by jimshepherd's avatar jimshepherd Committed by GitHub

Use state value in DropdownButtonFieldForm (#37145)

The current implementation of DropdownButtonFormField does not pass the initial value to _DropdownButtonFormFieldState. As a result changes made through the child DropdownButton are not made to the FormFieldState and the widget is not updated unless a onChanged function is provided to the DropdownButtomFormField constructor.

This change modifies DropdownButtonFormField to behave more consistently with other FormField widgets in how the Form state is handled.
parent 082ae838
......@@ -1427,19 +1427,20 @@ class DropdownButtonFormField<T> extends FormField<T> {
validator: validator,
autovalidate: autovalidate,
builder: (FormFieldState<T> field) {
final _DropdownButtonFormFieldState<T> state = field as _DropdownButtonFormFieldState<T>;
final InputDecoration effectiveDecoration = decoration.applyDefaults(
Theme.of(field.context).inputDecorationTheme,
);
return InputDecorator(
decoration: effectiveDecoration.copyWith(errorText: field.errorText),
isEmpty: value == null,
isEmpty: state.value == null,
child: DropdownButtonHideUnderline(
child: DropdownButton<T>(
value: value,
value: state.value,
items: items,
selectedItemBuilder: selectedItemBuilder,
hint: hint,
onChanged: onChanged == null ? null : field.didChange,
onChanged: onChanged == null ? null : state.didChange,
disabledHint: disabledHint,
elevation: elevation,
style: style,
......
......@@ -360,6 +360,63 @@ void main() {
}
});
testWidgets('Dropdown form field uses form field state', (WidgetTester tester) async {
final Key buttonKey = UniqueKey();
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String value;
await tester.pumpWidget(
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return MaterialApp(
home: Material(
child: Form(
key: formKey,
child: DropdownButtonFormField<String>(
key: buttonKey,
value: value,
hint: const Text('Select Value'),
decoration: const InputDecoration(
prefixIcon: Icon(Icons.fastfood)
),
items: menuItems.map((String val) {
return DropdownMenuItem<String>(
value: val,
child: Text(val)
);
}).toList(),
validator: (String v) => v == null ? 'Must select value' : null,
onChanged: (String newValue) {},
onSaved: (String v) {
setState(() {
value = v;
});
},
),
),
),
);
}
)
);
int getIndex() {
final IndexedStack stack = tester.element(find.byType(IndexedStack)).widget as IndexedStack;
return stack.index;
}
// Initial value of null displays hint
expect(value, equals(null));
expect(getIndex(), 4);
await tester.tap(find.text('Select Value'));
await tester.pumpAndSettle();
await tester.tap(find.text('three').last);
await tester.pumpAndSettle();
expect(getIndex(), 2);
// Changes only made to FormField state until form saved
expect(value, equals(null));
final FormState form = formKey.currentState;
form.save();
expect(value, equals('three'));
});
testWidgets('Dropdown in ListView', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/12053
// Positions a DropdownButton at the left and right edges of the screen,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment