1

I am not getting the desired outcome when using the typeahead package.

Current undesired behaviors:

  • when I tap on the text field I'm immediately shown the list of all suggestions (over 26,000) before I even begin typing

  • when I start typing, the list of suggestions does not adjust (for instance if I type "a" the full list of suggestions shows and the list doesn't filter to only show me suggestions beginning with "a"

Desired outcome:

  • I simply want the feature to show me the suggestions based on what I type-- I've implemented my code wrong I'm sure and would really appreciate any help!

My relevant code:

import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';

import '../providers/analysis_route_provider.dart';

class AutoCompleteTextfieldTwo extends StatefulWidget {
  @override
  _AutoCompleteTextfieldTwoState createState() =>
      _AutoCompleteTextfieldTwoState();
}

class _AutoCompleteTextfieldTwoState extends State<AutoCompleteTextfieldTwo> {
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return TypeAheadField(
      hideOnEmpty: true,
      textFieldConfiguration: TextFieldConfiguration(
        style: TextStyle(
          color: Colors.white,
        ),
        autofocus: false,
        controller: this._controller,
        keyboardType: TextInputType.text,
        enabled: true,
        focusNode: FocusNode(),
        decoration: InputDecoration(
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(20),
            borderSide: BorderSide(
              width: 2,
              color: Colors.blue,
            ),
          ),
          hintText: 'Type in company name or ticker symbol',
          hintStyle: TextStyle(
            color: Colors.grey,
          ),
        ),
      ),
      getImmediateSuggestions: true,
      hideOnError: true,
      suggestionsCallback: (pattern) async {
        return await AnalysisRouteProvider.getCompaniesForTextfield2(pattern);
      },
      itemBuilder: (context, itemData) {
        return ListTile(
          title: Text(itemData['name'].toString()),
          subtitle: Text(itemData['symbol'].toString()),
        );
      },
      onSuggestionSelected: (suggestion) {
        print('selected');

        FocusNode().unfocus();
        this._controller.text = suggestion['name'].toString();
        _controller.clear();
      },
    );
  }
}

Http request:

 static Future getCompaniesForTextfield2(String query) async {
    var url = *url with api key here*;
    http.Response response = await http.get(url, headers: {
      'Content-Type': 'application/json',
    });
    var jsonData = json.decode(response.body);

    return jsonData;
  }

JSON snippet (actual return from API has over 26,000 objects):

[ {
  "symbol" : "SPY",
  "name" : "SPDR S&P 500",
  "price" : 326.7,
  "exchange" : "NYSE Arca"
}, {
  "symbol" : "CMCSA",
  "name" : "Comcast Corp",
  "price" : 41.98,
  "exchange" : "Nasdaq Global Select"
}, {
  "symbol" : "KMI",
  "name" : "Kinder Morgan Inc",
  "price" : 11.83,
  "exchange" : "New York Stock Exchange"
}]

I'm also sure this bit of information is relevant. Currently, when I'm debugging and tap the typeahead text field, I get the following in the debug console:

W/IInputConnectionWrapper(13704): beginBatchEdit on inactive InputConnection
W/IInputConnectionWrapper(13704): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(13704): getTextAfterCursor on inactive InputConnection
W/IInputConnectionWrapper(13704): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper(13704): endBatchEdit on inactive InputConnection
student
  • 11
  • 2

2 Answers2

0

I think you should set getImadiateSugetions on false to disable the showing up the suggestion list onTap.

About the second problem, where you don't get suggetions, I think problem is in json, you are using json.decode, which decodes any json which is in [] to list, and in map if it is in {} so what I think you should do is following:

suggestionsCallback: (pattern) async {
        var list = await AnalysisRouteProvider.getCompaniesForTextfield2(pattern);
        return list[0];
      },
man of knowledge
  • 1,077
  • 7
  • 13
  • thank you for your willingness to help me out! I've implemented the code you suggested, but it still isn't quite giving me the behavior I want. Although I don't get immediate suggestions when I initially type on the text field; I also don't get any suggestions when I type in the text field--i.e. getting companies that start with "a" when I type in "a" and so on – student Oct 29 '20 at 03:39
0
  1. to solve your first problem just add minCharsForSuggestions property.

Example:

TypeAheadField(
          minCharsForSuggestions: 3,
)
  1. To solve your second problem, You should add some filter to your list of suggestions.

Example:

suggestionsCallback: (pattern) {
            return await AnalysisRouteProvider.getCompaniesForTextfield2(pattern).where(
              (e) => e['name'].toLowerCase().startsWith(
                    pattern.toLowerCase(),
                  ),
            );
          },
Maciej Szakacz
  • 381
  • 1
  • 6