flutterflutter-typeahead

Flutter TypeAhead Issue


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.


Solution

  • 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,
                )
              ],
            ),
          ),
        );
      }
    }
    

    enter image description here