How do I search in Flutter DropDown button
Asked Answered
V

5

14

I have a list of the countries name in local json. I can load my local json and assign to DropDown button. there is a 193 countries in json file as ex. shown below. If I want to select United State, user have to scroll all the way down. How can enter a countries name such as; if I user enter U or u the dropdown can makes quick filtering and list all the countries that starts with U such as United State. How do I search in Flutter DropDownbutton items?

{
    "country": [
        {
            "countryCode": "AD",
            "countryName": "Andorra",
            "currencyCode": "EUR",
            "isoNumeric": "020"
        },
        {
            "countryCode": "AE",
            "countryName": "United Arab Emirates",
            "currencyCode": "AED",
            "isoNumeric": "784"
        },
        {
            "countryCode": "AF",
            "countryName": "Afghanistan",
            "currencyCode": "AFN",
            "isoNumeric": "004"
        },
        //...
    ]
}
Verla answered 19/11, 2018 at 9:58 Comment(1)
you can use dropdown_search #59382192Phila
C
9

You can use searchable_dropdown package instead: https://pub.dev/packages/searchable_dropdown

And here is my example code searchable_dropdown dont work with class list

Make sure that you put the following if you use a class list like my example

  @override
  String toString() {
    return this.key;
  }
Cleanshaven answered 2/2, 2020 at 13:23 Comment(1)
this package gives an error subhead not found.Giggle
F
5

One way is to use a TextEditingController to filter your ListView like this:

class YourPage extends StatefulWidget {
  @override
  State createState() => YourPageState();
}

class YourPageState extends State<YourPage> {
  List<Country> countries = new List<Country>();
  TextEditingController controller = new TextEditingController();
  String filter;

  @override
  void initState() {
    super.initState();
    //fill countries with objects
    controller.addListener(() {
      setState(() {
        filter = controller.text;
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Material(
        color: Colors.transparent,
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            new Padding(
                padding: new EdgeInsets.only(top: 8.0, left: 16.0, right: 16.0),
                child: new TextField(
                  style: new TextStyle(fontSize: 18.0, color: Colors.black),
                  decoration: InputDecoration(
                    prefixIcon: new Icon(Icons.search),
                    suffixIcon: new IconButton(
                      icon: new Icon(Icons.close),
                      onPressed: () {
                        controller.clear();
                        FocusScope.of(context).requestFocus(new FocusNode());
                      },
                    ),
                    hintText: "Search...",
                  ),
                  controller: controller,
                )),
            new Expanded(
              child: new Padding(
                  padding: new EdgeInsets.only(top: 8.0),
                  child: _buildListView()),
            )
          ],
        ));
  }

  Widget _buildListView() {
    return ListView.builder(
        itemCount: countries.length,
        itemBuilder: (BuildContext context, int index) {
          if (filter == null || filter == "") {
            return _buildRow(countries[index]);
          } else {
            if (countries[index].countryName
                .toLowerCase()
                .contains(filter.toLowerCase())) {
              return _buildRow(countries[index]);
            } else {
              return new Container();
            }
          }
        });
  }

  Widget _buildRow(Country c) {
    return new ListTile(
        title: new Text(
          c.countryName,
        ),
        subtitle: new Text(
          c.countryCode,
        ));
  }
}
Fess answered 19/11, 2018 at 10:7 Comment(3)
SnakeyHips you misunderstood my question. My dropdown button inside a ListView, and I assign my data to my dropdown button. I am looking way so I can search or filter the dropdown button with user interaction.Verla
@Verla SnakeyHips is right. You have to use a ListView with TextField column widget in a dialog instead of the drop down. In fact the drop down is bad choice for big lists like country list. I mean it's not html.Pero
This is great solution, however flutter doesn't load all the countries at once, so we cannot filter for mid to low level records. A better solution is to have another filtered list of countries and fill/clear this according to filter and we can put this code directly in the listener.Pero
T
2

This is a bit old I think, as now using just the included material package and utilizing the DropDownMenu widget works. You use the enableFilter: True property to enable the manual search. If you somehow click the widget and it doesn't allow you to type for searching, then adding the property requestFocusOnTap: true helps especially in ListViews / ListTiles / Scrollables Cards

DropdownMenu<CountryEntity>(
        controller: countryController,
        label: const Text('Country'),
        width: 300,
        dropdownMenuEntries: countryEntities,
        enableFilter: true,
        menuStyle: const MenuStyle(
            alignment: Alignment.bottomLeft,
            maximumSize:
                MaterialStatePropertyAll(Size.fromHeight(Sizes.p124)),),
        requestFocusOnTap: true,
        onSelected: (country) {
          setState(() {
            selectedCountryId = country;
          });
        },
      );
Transept answered 14/8, 2023 at 13:39 Comment(0)
L
1

You can use dropdown_search package like below.

import 'package:dropdown_search/dropdown_search.dart';

DropdownSearch<String>(
    popupProps: PopupProps.menu(
        showSearchBox: true,
        showSelectedItems: true,
        disabledItemFn: (String s) => s.startsWith('I'),
    ),
    items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
    dropdownDecoratorProps: DropDownDecoratorProps(
        dropdownSearchDecoration: InputDecoration(
            labelText: "Menu mode",
            hintText: "country in menu mode",
        ),
    ),
    onChanged: print,
    selectedItem: "Brazil",
)

Make sure you have set showSearchBox attribute under popupProps. This attribute is not yet mentioned in the documentation. See PopupProps source code for more attributes.

Laundryman answered 13/5, 2023 at 5:51 Comment(3)
Hi @ruwan800, I am using this dropdownSearch widget and showing a simple list, but I want to show a section list in dropdownSearch widget, is it possible to show a section list?Timeless
I don't get what do meant by section list? Do you need to add separators in between some list items?Laundryman
No, I was trying to show Items below a particular section, for ex: Section1: Item1, Item2, Item3, below the section in the list.Timeless
M
0

Use textfield_search: ^0.8.0 plugin view sample

            TextFieldSearch(
            decoration: InputDecoration(
              hintText: "Search",
              prefixIcon: Icon(
                Icons.search,
                color: Colors.black45,
              ),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8.0),
                borderSide: BorderSide.none,
              ),
              filled: true,
              fillColor: Colors.grey[200],
            ),
            initialList: constants.VEHICLELIST,
            label: "label",
            controller: selectedVehicle),
Moleskins answered 30/9, 2021 at 16:29 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.