Search code examples
flutterdartflutter-layoutflutter-dependenciesflutter-animation

Use the TypeAheadFormField inside a Form - Flutter


I'm facing difficulties to add a selected option after clicking from the suggestion to the searcher, (adding a selected option to the form).

When the options are displayed after typing a few letters I would like to press the suggestion and then it should appear in form , I'm new to flutter and I don't know exactly how to do it, any possible help is greatly appreciated.

Maybe there are other options thanks to which it will be possible to do this, after entering word and click searcher icon new container will appear

       void search(String query) {
      setState(() {
    pickedValues.add(query);
});
}

Widget _buildSearchBar() {
return Column(mainAxisSize: MainAxisSize.min, children: [
  ConstrainedBox(
    constraints: const BoxConstraints.tightFor(width: 350),
    child: TypeAheadField<Breed?>(
      // ask server after 500
      debounceDuration: Duration(milliseconds: 500),
      hideSuggestionsOnKeyboardHide: false,
      textFieldConfiguration: TextFieldConfiguration(
        controller: controller,
        // onFieldSubmitted: search,
        decoration: InputDecoration(
          labelText: 'Search',
          hintText: 'Search',
          fillColor: Colors.white,
          filled: true,
          isDense: true,
          suffixIcon: GestureDetector(
            onTap: () {
              controller.clear();
            },
            child: const Padding(
              padding: EdgeInsets.symmetric(
                horizontal: 10,
                vertical: 10,
              ),
              child: Icon(
                Icons.clear,
                size: 30,
              ),
            ),
          ),
          prefixIcon: GestureDetector(
            onTap: () {
             search(controller.text) ;
            },

            /// widget isntead of normal button
            // cancellationWidget: Text("Cancel"),
            child: const Padding(
              padding: EdgeInsets.symmetric(
                horizontal: 10,
                vertical: 10,
              ),
              child: Icon(
                Icons.search_outlined,
                size: 30,
              ),
            ),
          ),
          focusedBorder: const OutlineInputBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(30),
            ),
            borderSide: BorderSide(
              width: 2,
              color: Colors.teal,
            ),
          ),
          disabledBorder: InputBorder.none,
          border: InputBorder.none,
          enabledBorder: const OutlineInputBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(30),
            ),
            borderSide: BorderSide(
              width: 2,
              color: Colors.grey,
            ),
          ),
          errorBorder: const OutlineInputBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(5),
            ),
            borderSide: BorderSide(
              width: 2,
              color: Colors.red,
            ),
          ),
        ),
      ),
      suggestionsCallback: BreedApi.getBreedSuggestions,
      itemBuilder: (context, Breed? suggestion) {
        final breed = suggestion!;
        return ListTile(
          title: Text(breed.name),
        );
      },
      noItemsFoundBuilder: (context) => Container(
        height: 100,
        child: Center(
          child: Text(
            'No Breed Found.',
            style: TextStyle(fontSize: 24),
          ),
        ),
      ),
      onSuggestionSelected: (Breed? suggestion) {
        final breed = suggestion!;

        ScaffoldMessenger.of(context)
          ..removeCurrentSnackBar()
          ..showSnackBar(SnackBar(
            content: Text('Selected breed: ${breed.name}'),
          ));
      },
    ),
  )
]);
}

enter image description here

part of api of breed:

class Breed {
 final String name;

const Breed({
  required this.name,
});

static Breed fromJson(Map<String, dynamic> json) => Breed(
  name: json['name'],
);
}

class BreedApi {
  static Future<List<Breed>> getBreedSuggestions(String query) async {
final url = Uri.parse('https://api.thedogapi.com/v1/breeds');
final response = await http.get(url);

if (response.statusCode == 200) {
  final List breeds = json.decode(response.body);

  return breeds.map((json) => Breed.fromJson(json)).where((breed) {
    final nameLower = breed.name.toLowerCase();
    final queryLower = query.toLowerCase();

    return nameLower.contains(queryLower);
  }).toList();
} else {
  throw Exception();
  }
   }
    }

Solution

  • use the onTap method of ListTile in suggestionsCallback Function and send the selected name to a new screen or just send it to a function using the named parameter.

    suggestionsCallback: BreedApi.getBreedSuggestions,
      itemBuilder: (context, Breed? suggestion) {
        final breed = suggestion!;
        return ListTile(
          onTap:(){
                  ScreenName(name: breed.name) or FunctionName(breed.name);
                  }
          title: Text(breed.name),
        );
      },