I am trying to implement the Flutter Typeahead based on the following link: Flutter TypeAhead
class _CallAddState extends State<CallAdd> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _typeAheadController = TextEditingController();
var SerVerConfig = [
{
"name":"Mike",
"id":"1"
},
{
"name":"Bill",
"id":"2"
},
{
"name":"Juan",
"id":"3"
},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Form(
key: this._formKey,
child: Padding(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
style: DefaultTextStyle.of(context)
.style
.copyWith(fontStyle: FontStyle.italic),
decoration:
InputDecoration(border: OutlineInputBorder())),
suggestionsCallback: (pattern) async {
return SerVerConfig;
},
itemBuilder: (context, suggestion) {
print("item builder " + suggestion);
return ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(suggestion['name']),
// subtitle: Text('\$${suggestion['id']}'),
);
},
onSuggestionSelected: (suggestion) {
Navigator.of(context).push(MaterialPageRoute(
// builder: (context) => ProductPage(product: suggestion)
));
},
)
],
),
),
));
}
}
Unfortunately, I am getting an error with the following message in the suggestionsCallback function. "type '_InternalLinkedHashMap' is not a subtype of type 'String'
Any help or advice is much appreciated. Thanks.
SerVerConfig use List, you can compare difference
You can see full code and demo picture (Example 2: Form)
code snippet
List SerVerConfig = [
{"name": "Mike", "id": "1"},
{"name": "Bill", "id": "2"},
{"name": "Juan", "id": "3"},
];
TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
style: DefaultTextStyle.of(context)
.style
.copyWith(fontStyle: FontStyle.italic),
decoration: InputDecoration(border: OutlineInputBorder())),
suggestionsCallback: (pattern) async {
return SerVerConfig;
},
itemBuilder: (context, suggestion) {
return ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(suggestion['name']),
// subtitle: Text('\$${suggestion['id']}'),
);
},
onSuggestionSelected: (suggestion) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductPage(product: suggestion)));
},
),
full code
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:example/data.dart';
class MyMaterialApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'flutter_typeahead demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: TabBar(tabs: [
Tab(text: 'Example 1: Navigation'),
Tab(text: 'Example 2: Form'),
Tab(text: 'Example 3: Scroll')
]),
),
body: TabBarView(children: [
NavigationExample(),
FormExample(),
ScrollExample(),
])),
);
}
}
class NavigationExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
style: DefaultTextStyle.of(context)
.style
.copyWith(fontStyle: FontStyle.italic),
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'What are you looking for?'),
),
suggestionsCallback: (pattern) async {
var fruits = ['bananas', 'apples', 'oranges'];
return await BackendService.getSuggestions(pattern);
},
itemBuilder: (context, suggestion) {
return ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(suggestion['name']),
subtitle: Text('\$${suggestion['price']}'),
);
},
onSuggestionSelected: (suggestion) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductPage(product: suggestion)));
},
),
],
),
);
}
}
class FormExample extends StatefulWidget {
@override
_FormExampleState createState() => _FormExampleState();
}
class _FormExampleState extends State<FormExample> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _typeAheadController = TextEditingController();
String _selectedCity;
List SerVerConfig = [
{"name": "Mike", "id": "1"},
{"name": "Bill", "id": "2"},
{"name": "Juan", "id": "3"},
];
@override
Widget build(BuildContext context) {
return Form(
key: this._formKey,
child: Padding(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
Text('What is your favorite city?'),
TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
decoration: InputDecoration(labelText: 'City'),
controller: this._typeAheadController,
),
suggestionsCallback: (pattern) {
//var fruits = ['bananas', 'apples', 'oranges'];
return CitiesService.getSuggestions(pattern);
},
itemBuilder: (context, suggestion) {
return ListTile(
title: Text(suggestion),
);
},
transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (suggestion) {
this._typeAheadController.text = suggestion;
},
validator: (value) {
if (value.isEmpty) {
return 'Please select a city';
}
},
onSaved: (value) => this._selectedCity = value,
),
TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
style: DefaultTextStyle.of(context)
.style
.copyWith(fontStyle: FontStyle.italic),
decoration: InputDecoration(border: OutlineInputBorder())),
suggestionsCallback: (pattern) async {
return SerVerConfig;
},
itemBuilder: (context, suggestion) {
return ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(suggestion['name']),
// subtitle: Text('\$${suggestion['id']}'),
);
},
onSuggestionSelected: (suggestion) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductPage(product: suggestion)));
},
),
SizedBox(
height: 10.0,
),
RaisedButton(
child: Text('Submit'),
onPressed: () {
if (this._formKey.currentState.validate()) {
this._formKey.currentState.save();
Scaffold.of(context).showSnackBar(SnackBar(
content:
Text('Your Favorite City is ${this._selectedCity}')));
}
},
)
],
),
),
);
}
}
class ScrollExample extends StatelessWidget {
final List<String> items = List.generate(5, (index) => "Item $index");
@override
Widget build(BuildContext context) {
return ListView(children: [
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Suggestion box will resize when scrolling"),
)),
SizedBox(height: 200),
TypeAheadField<String>(
getImmediateSuggestions: true,
textFieldConfiguration: TextFieldConfiguration(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'What are you looking for?'),
),
suggestionsCallback: (String pattern) async {
return items
.where((item) =>
item.toLowerCase().startsWith(pattern.toLowerCase()))
.toList();
},
itemBuilder: (context, String suggestion) {
return ListTile(
title: Text(suggestion),
);
},
onSuggestionSelected: (String suggestion) {
print("Suggestion selected");
},
),
SizedBox(height: 500),
]);
}
}
class ProductPage extends StatelessWidget {
final Map<String, dynamic> product;
ProductPage({this.product});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(50.0),
child: Column(
children: [
Text(
this.product['name'],
style: Theme.of(context).textTheme.headline,
),
Text(
this.product['price'].toString() + ' USD',
style: Theme.of(context).textTheme.subhead,
)
],
),
),
);
}
}