Unverified Commit 29d33cc3 authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Autocomplete Split UI (#72553)

Allows passing in a TextEditingController and FocusNode to RawAutocomplete, which enables split UIs where the TextField is in another part of the tree from the results.
parent 5c6640df
...@@ -45,7 +45,6 @@ void main() { ...@@ -45,7 +45,6 @@ void main() {
User(name: 'Charlie', email: 'charlie123@gmail.com'), User(name: 'Charlie', email: 'charlie123@gmail.com'),
]; ];
group('RawAutocomplete', () {
testWidgets('can filter and select a list of string options', (WidgetTester tester) async { testWidgets('can filter and select a list of string options', (WidgetTester tester) async {
final GlobalKey fieldKey = GlobalKey(); final GlobalKey fieldKey = GlobalKey();
final GlobalKey optionsKey = GlobalKey(); final GlobalKey optionsKey = GlobalKey();
...@@ -327,6 +326,9 @@ void main() { ...@@ -327,6 +326,9 @@ void main() {
), ),
); );
expect(find.byKey(fieldKey), findsOneWidget);
expect(find.byKey(optionsKey), findsNothing);
// Enter text. The options are filtered by the text. // Enter text. The options are filtered by the text.
focusNode.requestFocus(); focusNode.requestFocus();
textEditingController.value = const TextEditingValue( textEditingController.value = const TextEditingValue(
...@@ -486,5 +488,70 @@ void main() { ...@@ -486,5 +488,70 @@ void main() {
expect(lastOptions.elementAt(0), 'chameleon'); expect(lastOptions.elementAt(0), 'chameleon');
expect(lastOptions.elementAt(1), 'elephant'); expect(lastOptions.elementAt(1), 'elephant');
}); });
testWidgets('can create a field outside of fieldViewBuilder', (WidgetTester tester) async {
final GlobalKey fieldKey = GlobalKey();
final GlobalKey optionsKey = GlobalKey();
final GlobalKey autocompleteKey = GlobalKey();
late Iterable<String> lastOptions;
final FocusNode focusNode = FocusNode();
final TextEditingController textEditingController = TextEditingController();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(
// This is where the real field is being built.
title: TextFormField(
key: fieldKey,
controller: textEditingController,
focusNode: focusNode,
onFieldSubmitted: (String value) {
RawAutocomplete.onFieldSubmitted(autocompleteKey);
},
),
),
body: RawAutocomplete<String>(
key: autocompleteKey,
focusNode: focusNode,
textEditingController: textEditingController,
optionsBuilder: (TextEditingValue textEditingValue) {
return kOptions.where((String option) {
return option.contains(textEditingValue.text.toLowerCase());
});
},
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<String> onSelected, Iterable<String> options) {
lastOptions = options;
return Container(key: optionsKey);
},
),
),
),
);
expect(find.byKey(fieldKey), findsOneWidget);
expect(find.byKey(optionsKey), findsNothing);
// Enter text. The options are filtered by the text.
focusNode.requestFocus();
textEditingController.value = const TextEditingValue(
text: 'ele',
selection: TextSelection(baseOffset: 3, extentOffset: 3),
);
await tester.pump();
expect(find.byKey(fieldKey), findsOneWidget);
expect(find.byKey(optionsKey), findsOneWidget);
expect(lastOptions.length, 2);
expect(lastOptions.elementAt(0), 'chameleon');
expect(lastOptions.elementAt(1), 'elephant');
// Submit the field. The options hide and the field updates to show the
// selection.
await tester.showKeyboard(find.byType(TextFormField));
await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pump();
expect(find.byKey(fieldKey), findsOneWidget);
expect(find.byKey(optionsKey), findsNothing);
expect(textEditingController.text, lastOptions.elementAt(0));
}); });
} }
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