mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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.
This commit is contained in:
parent
082ae838bd
commit
92a335e465
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user