Search code examples
flutterdropdownsearchable

dropdown_button2 Search is Not Working with Class List


I have a dropdown button which I implemented using dropdown_button2 1.9.2.

I want to make the dropdown_button searchable.

I tried implementing it with my custom class but it won't work.

I have tried overriding the toString method of my class (as suggested in this answer) but it still won't work.

Please any fix or am I doing something wrong here?

This is the dropdown button

enter image description here

This is what it does when I try searching for an item in the dropdown. enter image description here

This is my full code:

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

// ignore_for_file: public_member_api_docs, sort_constructors_first
class MyDropDownItems {
  MyDropDownItems({
    required this.text,
    required this.value,
  });

  String text;
  String value;

  @override
  String toString() {
    return value;
  }
}

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

  @override
  State<MoodScreen> createState() => _MoodScreenState();
}

class _MoodScreenState extends State<MoodScreen> {
  final TextEditingController _textEditingController = TextEditingController();

  // Initial Selected Value
  String _dropdownvalue = ' ';

  final _dropDownItems = [
    MyDropDownItems(text: "Select Mood", value: " "),
    MyDropDownItems(text: "Mood 1", value: "happy"),
    MyDropDownItems(text: "Mood 2", value: "Sad"),
    MyDropDownItems(text: "Mood 3", value: "Confused"),
    MyDropDownItems(text: "Mood 4", value: "Lonely"),
    MyDropDownItems(text: "Mood 5", value: "Excited"),
    MyDropDownItems(text: "Mood 6", value: "Wealthy"),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 300,
              padding: const EdgeInsets.symmetric(
                horizontal: 12,
                vertical: 4,
              ),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.green, width: 4),
              ),
              child: DropdownButtonHideUnderline(
                child: DropdownButton2(
                  searchController: _textEditingController,
                  searchInnerWidget: Padding(
                    padding: const EdgeInsets.only(
                      top: 8,
                      bottom: 4,
                      right: 8,
                      left: 8,
                    ),
                    child: TextFormField(
                      controller: _textEditingController,
                      decoration: const InputDecoration(
                        isDense: true,
                        hintText: 'Select mood...',
                        contentPadding: EdgeInsets.symmetric(
                          horizontal: 10,
                          vertical: 8,
                        ),
                      ),
                    ),
                  ),
                  searchMatchFn: (item, searchValue) {
                    return (item.value.toString().contains(searchValue));
                  },
                  onMenuStateChange: (isOpen) {
                    if (!isOpen) {
                      _textEditingController.clear();
                    }
                  },
                  value: _dropdownvalue,
                  isExpanded: true,
                  iconSize: 36,
                  iconEnabledColor: Colors.green,
                  icon: const Icon(
                    Icons.arrow_drop_down_circle,
                  ),
                  items: _dropDownItems.map((MyDropDownItems networkNumbers) {
                    return DropdownMenuItem(
                      value: networkNumbers.value,
                      child: Text(networkNumbers.text),
                    );
                  }).toList(),
                  onChanged: (value) {
                    setState(() {
                      _dropdownvalue = value!;
                    });
                  },
                ),
              ),
            ),
            const SizedBox(height: 20),
            Text("The mood is: $_dropdownvalue"),
          ],
        ),
      ),
    );
  }
}

Solution

  • If you really want to search by the display name, then searchMatchFn should be as following

    searchMatchFn: (item, searchValue) {
        final myItem = _dropDownItems.firstWhere((element) => element.value == item.value);
        return myItem.text.contains(searchValue);
    }
    

    or if you need search based on value and text, then

    searchMatchFn: (item, searchValue) {
        final myItem = _dropDownItems.firstWhere((element) => element.value == item.value);
        return myItem.text.contains(searchValue) || item.value.toString().contains(searchValue);
    }