search_field_dropdown 1.0.4+2 copy "search_field_dropdown: ^1.0.4+2" to clipboard
search_field_dropdown: ^1.0.4+2 copied to clipboard

A customizable dropdown widget for Flutter with advanced styling, search functionality, and dynamic data handling.

example/lib/main.dart

import 'dart:convert';
import 'package:search_field_dropdown/search_field_dropdown.dart';
import 'Model/city_model.dart';
import 'Model/states_model.dart';
import 'Model/country_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FormFiled DropDown Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          primary: Colors.deepPurple,
        ),
        appBarTheme: const AppBarTheme(
          color: Colors.deepPurple,
        ),
        useMaterial3: true,
      ),
      home: const DropDownClass(),
    );
  }
}

class DropDownClass extends StatefulWidget {
  const DropDownClass({super.key});

  @override
  State<DropDownClass> createState() => _DropDownClassState();
}

class _DropDownClassState extends State<DropDownClass> {
  final countryController = OverlayPortalController();
  List<OverlayPortalController> countryController1 = [];
  final stateController = OverlayPortalController();
  final cityController = OverlayPortalController();
  final itemController = OverlayPortalController();

  CountryModel? selectedCountry;
  StatesModel? selectedState;
  CityModel? selectedCity;

  List<StatesModel> tempStatesList = [];
  List<CountryModel> countryList = [];
  List<StatesModel> statesList = [];
  List<CityModel> tempCityList = [];
  List<CityModel> cityList = [];

  FocusNode focusNode = FocusNode();
  FocusNode focusNode2 = FocusNode();
  FocusNode focusNode3 = FocusNode();

  Future<void> loadCity() async {
    cityList = [];

    var data = await rootBundle.loadString("assets/JsonFiles/City.json");
    var cityData = json.decode(data);
    List list = cityData['city'].cast<Map<String, dynamic>>();
    cityList.addAll(list.map((e) => CityModel.fromJson(e)).toList());
    setState(() {});
  }

  Future<void> loadState() async {
    statesList = [];
    var data = await rootBundle.loadString("assets/JsonFiles/State.json");
    var stateData = json.decode(data);
    List list = stateData['states'].cast<Map<String, dynamic>>();
    statesList.addAll(list.map((e) => StatesModel.fromJson(e)).toList());
    setState(() {});
  }

  Future<void> loadCountry() async {
    countryList = [];
    var data = await rootBundle.loadString("assets/JsonFiles/Country.json");
    var countryData = json.decode(data);
    List list = countryData['countries'].cast<Map<String, dynamic>>();
    countryList.addAll(list.map((e) => CountryModel.fromJson(e)).toList());
    setState(() {});
  }

  bool isHidde = false;

  FocusNode focusNodes = FocusNode();

  @override
  void initState() {
    super.initState();
    loadCity();
    loadState();
    loadCountry();

    countryController1 =
        List.generate(15, (index) => OverlayPortalController());
  }

  final GlobalKey<SearchFieldDropdownState<String>> dropdownKey1 =
      GlobalKey<SearchFieldDropdownState<String>>();
  final GlobalKey<SearchFieldDropdownState<String>> dropdownKey2 =
      GlobalKey<SearchFieldDropdownState<String>>();
  final GlobalKey<SearchFieldDropdownState<String>> dropdownKey3 =
      GlobalKey<SearchFieldDropdownState<String>>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "FormFiled DropDown Example",
          style: TextStyle(color: Colors.white),
        ),
      ),
      body: CallbackShortcuts(
        bindings: {
          LogicalKeySet(LogicalKeyboardKey.tab): () async {
            if (focusNode.hasFocus) {
              focusNode2.requestFocus();
              stateController.show();
              countryController.hide();
              cityController.hide();
            } else if (focusNode2.hasFocus) {
              focusNode3.requestFocus();
              stateController.hide();
              countryController.hide();
              cityController.show();
            } else if (focusNode3.hasFocus) {
              focusNode.requestFocus();
              stateController.hide();
              cityController.hide();
              countryController.show();
            }
          }
        },
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Row(
                children: [
                  Expanded(
                      child: SearchFieldDropdown<CountryModel>(
                    focusNode: focusNode,
                    enableInteractiveSelection: true,
                    autovalidateMode: AutovalidateMode.onUserInteraction,
                    controller: countryController,
                    initialItem: selectedCountry,
                    item: countryList,
                    textStyle: const TextStyle(
                        fontSize: 12, fontWeight: FontWeight.w400),
                    menuDecoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(color: Colors.blueAccent),
                    ),
                    filedDecoration: InputDecoration(
                      suffixIcon: IntrinsicWidth(
                        child: Row(
                          children: [
                            if (selectedCountry != null)
                              InkWell(
                                onTap: () {
                                  setState(() {
                                    isHidde = false;
                                    tempCityList = [];
                                    tempStatesList = [];
                                    // print(tempStatesList.length);
                                    selectedCity = null;
                                    selectedState = null;
                                    selectedCountry = null;
                                    loadCountry();
                                  });
                                },
                                child: const Icon(
                                  Icons.clear,
                                  size: 20,
                                ),
                              ),
                            if (selectedCountry != null)
                              const SizedBox(width: 5),
                            const Icon(
                              Icons.arrow_drop_down_sharp,
                              size: 20,
                            ),
                            const SizedBox(width: 8),
                          ],
                        ),
                      ),
                    ),
                    onChanged: (CountryModel? value) {
                      selectedCountry = value;
                      setState(() {});
                    },
                    onSearch: (value) async {
                      return countryList.where((element) {
                        return element.name
                            .toLowerCase()
                            .contains(value.toLowerCase());
                      }).toList();
                    },
                    listItemBuilder: (context, item, isSelected) {
                      int index = countryList.indexOf(item);
                      return Container(
                        padding: const EdgeInsets.symmetric(
                            horizontal: 5, vertical: 5),
                        margin:
                            EdgeInsets.fromLTRB(5, index == 0 ? 7 : 2, 5, 1),
                        decoration: BoxDecoration(
                            color:
                                isSelected ? Colors.green : Colors.transparent,
                            borderRadius: BorderRadius.circular(2)),
                        child: Text(
                          item.name,
                          style: TextStyle(
                              fontSize: 12,
                              color: isSelected ? Colors.white : Colors.black,
                              fontWeight: FontWeight.w400),
                        ),
                      );
                    },
                    selectedItemBuilder: (context, item) {
                      return Text(
                        item.name,
                        style: const TextStyle(
                            fontSize: 12, fontWeight: FontWeight.w400),
                      );
                    },
                  )),
                  const SizedBox(width: 15),
                  Expanded(
                      child: SearchFieldDropdown<StatesModel>(
                    focusNode: focusNode2,
                    autovalidateMode: AutovalidateMode.onUserInteraction,
                    controller: stateController,
                    initialItem: selectedState,
                    item: tempStatesList,
                    textStyle: const TextStyle(
                        fontSize: 12, fontWeight: FontWeight.w400),
                    menuDecoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(10),
                      border: Border.all(color: Colors.blueAccent),
                    ),
                    filedDecoration: InputDecoration(
                      suffixIcon: IntrinsicWidth(
                        child: Row(
                          children: [
                            if (selectedState != null)
                              InkWell(
                                onTap: () {
                                  setState(() {
                                    selectedState = null;
                                    if (selectedCountry == null) {
                                      tempStatesList.clear();
                                    }
                                  });
                                },
                                child: const Icon(
                                  Icons.clear,
                                  size: 20,
                                ),
                              ),
                            if (selectedState != null) const SizedBox(width: 5),
                            const Icon(
                              Icons.arrow_drop_down_sharp,
                              size: 20,
                            ),
                            const SizedBox(width: 8),
                          ],
                        ),
                      ),
                    ),
                    onChanged: (StatesModel? value) {
                      setState(() {
                        tempCityList = [];
                        selectedCity = null;
                        selectedState = value;

                        tempCityList = cityList.where((element) {
                          return "${element.stateId}" == "${selectedState?.id}";
                        }).toList();
                      });
                    },
                    onSearch: (value) async {
                      return statesList.where((element) {
                        return element.name
                            .toLowerCase()
                            .contains(value.toLowerCase());
                      }).toList();
                    },
                    listItemBuilder: (context, item, isSelected) {
                      // print("isSelected $isSelected");
                      int index = statesList.indexOf(item);
                      return Container(
                        padding: const EdgeInsets.symmetric(
                            horizontal: 5, vertical: 5),
                        margin:
                            EdgeInsets.fromLTRB(5, index == 0 ? 7 : 2, 5, 1),
                        decoration: BoxDecoration(
                            color:
                                isSelected ? Colors.green : Colors.transparent,
                            borderRadius: BorderRadius.circular(2)),
                        child: Text(
                          item.name,
                          style: TextStyle(
                              fontSize: 12,
                              color: isSelected ? Colors.white : Colors.black,
                              fontWeight: FontWeight.w400),
                        ),
                      );
                    },
                    selectedItemBuilder: (context, item) {
                      return Text(
                        item.name,
                        style: const TextStyle(
                            fontSize: 12, fontWeight: FontWeight.w400),
                      );
                    },
                  )),
                  const SizedBox(width: 15),
                  Expanded(
                      child: SearchFieldDropdown<CityModel>(
                    focusNode: focusNode3,
                    autovalidateMode: AutovalidateMode.onUserInteraction,
                    controller: cityController,
                    readOnly: tempCityList.isEmpty,
                    initialItem: selectedCity,
                    item: tempCityList,
                    textStyle: const TextStyle(
                        fontSize: 12, fontWeight: FontWeight.w400),
                    menuDecoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(color: Colors.blueAccent)),
                    filedDecoration: InputDecoration(
                      suffixIcon: IntrinsicWidth(
                        child: Row(
                          children: [
                            if (selectedCity != null)
                              InkWell(
                                onTap: () {
                                  setState(() {
                                    selectedCity = null;
                                    if (selectedState == null) {
                                      tempCityList.clear();
                                    }
                                  });
                                },
                                child: const Icon(
                                  Icons.clear,
                                  size: 20,
                                ),
                              ),
                            if (selectedCity != null) const SizedBox(width: 5),
                            const Icon(
                              Icons.arrow_drop_down_sharp,
                              size: 20,
                            ),
                            const SizedBox(width: 8),
                          ],
                        ),
                      ),
                    ),
                    onChanged: (CityModel? value) {
                      setState(() {
                        selectedCity = value;
                      });
                    },
                    onSearch: (value) async {
                      return tempCityList.where((element) {
                        return element.name
                            .toLowerCase()
                            .contains(value.toLowerCase());
                      }).toList();
                    },
                    listItemBuilder: (context, item, isSelected) {
                      int index = cityList.indexOf(item);
                      return Container(
                        padding: const EdgeInsets.symmetric(
                            horizontal: 5, vertical: 5),
                        margin:
                            EdgeInsets.fromLTRB(5, index == 0 ? 7 : 2, 5, 1),
                        decoration: BoxDecoration(
                            color:
                                isSelected ? Colors.green : Colors.transparent,
                            borderRadius: BorderRadius.circular(2)),
                        child: Text(
                          item.name,
                          style: TextStyle(
                              fontSize: 12,
                              color: isSelected ? Colors.white : Colors.black,
                              fontWeight: FontWeight.w400),
                        ),
                      );
                    },
                    selectedItemBuilder: (context, item) {
                      return Text(
                        item.name,
                        style: const TextStyle(
                            fontSize: 12, fontWeight: FontWeight.w400),
                      );
                    },
                  ))
                ],
              ),

              // Expanded(
              //   child: ListView.builder(
              //     shrinkWrap: true,
              //     itemCount: 10,
              //     itemBuilder: (context, index) {
              //     return InkWell(
              //       onTap: () {
              //         Navigator.push(context, MaterialPageRoute(builder: (context) =>DropDownClass() ,));
              //       },
              //       child: Container(
              //         height: 50,
              //         margin: EdgeInsets.symmetric(vertical: 10),
              //         child: Text("hello"),
              //       )
              //     );
              //   },),
              // ),

              Expanded(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: 15,
                  itemBuilder: (context, index) {
                    return InkWell(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => DropDownClass(),
                            ));
                      },
                      child: SearchFieldDropdown<CountryModel>(
                        // focusNode: focusNode,
                        enableInteractiveSelection: true,
                        autovalidateMode: AutovalidateMode.onUserInteraction,
                        controller: countryController1[index],
                        initialItem: selectedCountry,
                        item: countryList,
                        textStyle: const TextStyle(
                            fontSize: 12, fontWeight: FontWeight.w400),
                        menuDecoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(4),
                          border: Border.all(color: Colors.blueAccent),
                        ),
                        filedDecoration: InputDecoration(
                          suffixIcon: IntrinsicWidth(
                            child: Row(
                              children: [
                                if (selectedCountry != null)
                                  InkWell(
                                    onTap: () {
                                      setState(() {
                                        isHidde = false;
                                        tempCityList = [];
                                        tempStatesList = [];
                                        // print(tempStatesList.length);
                                        selectedCity = null;
                                        selectedState = null;
                                        selectedCountry = null;
                                        loadCountry();
                                      });
                                    },
                                    child: const Icon(
                                      Icons.clear,
                                      size: 20,
                                    ),
                                  ),
                                if (selectedCountry != null)
                                  const SizedBox(width: 5),
                                const Icon(
                                  Icons.arrow_drop_down_sharp,
                                  size: 20,
                                ),
                                const SizedBox(width: 8),
                              ],
                            ),
                          ),
                        ),
                        onChanged: (CountryModel? value) {},
                        onSearch: (value) async {
                          return countryList.where((element) {
                            return element.name
                                .toLowerCase()
                                .contains(value.toLowerCase());
                          }).toList();
                        },
                        listItemBuilder: (context, item, isSelected) {
                          int index = countryList.indexOf(item);
                          return Container(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 5, vertical: 5),
                            margin: EdgeInsets.fromLTRB(
                                5, index == 0 ? 7 : 2, 5, 1),
                            decoration: BoxDecoration(
                                color: isSelected
                                    ? Colors.green
                                    : Colors.transparent,
                                borderRadius: BorderRadius.circular(2)),
                            child: Text(
                              item.name,
                              style: TextStyle(
                                  fontSize: 12,
                                  color:
                                      isSelected ? Colors.white : Colors.black,
                                  fontWeight: FontWeight.w400),
                            ),
                          );
                        },
                        selectedItemBuilder: (context, item) {
                          return Text(
                            item.name,
                            style: const TextStyle(
                                fontSize: 12, fontWeight: FontWeight.w400),
                          );
                        },
                      ),
                    );
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
6
likes
150
points
29
downloads

Publisher

unverified uploader

Weekly Downloads

A customizable dropdown widget for Flutter with advanced styling, search functionality, and dynamic data handling.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

cupertino_icons, flutter

More

Packages that depend on search_field_dropdown