I'm using a DropDownMenu in Flutter to search for items in my ProductList. As soon as I type something that wouldn't match the value of a product in the list, I get this error: RangeError (length): Invalid value: Valid value range is empty: 0
Here's the code that I tried:
products.when(
data: (productList) {
var filteredList = searchController.text.isNotEmpty ? productList
.where((e) => e.name.contains(RegExp(
searchController.text,
caseSensitive: false)))
.toList()
: productList.take(5).toList();
return SizedBox(
child: DropdownMenu<String?>(
textStyle: TextStyle(color: Colors.black),
inputDecorationTheme: InputDecorationTheme(
hintStyle: TextStyle(color: Colors.black),
helperStyle: TextStyle(color: Colors.black),
labelStyle: TextStyle(color: Colors.black),
),
controller: searchController,
width: 350,
hintText: "Search for a product...",
requestFocusOnTap: true,
enableFilter: true,
enabled: selectedProduct == null,
label: const Text('Select A Product'),
onSelected: (String? selectedProductName) {
setState(() {
selectedProduct = selectedProductName;
});
},
dropdownMenuEntries: filteredList.isEmpty
? [
DropdownMenuEntry<String?>(
value: '',
label: 'No results found.',
)
]
: filteredList.map<DropdownMenuEntry<String?>>(
(ProductModel product) {
return DropdownMenuEntry<String?>(
value: product.id.toString(),
label:
'${product.name} (${product.location})',
);
}).toList(),
),
);
},
error: (_, __) => getLoadError(_),
loading: () => getLoadIndicator(),
),
My productList loads fine.
EDIT: This error only occurs if the filteredList was populated by the search initially. If I search for something that doesn't exist initially, it wouldn't give me this error.. For example, if this list contains [Apples, Oranges] and I search "OA" I get the error, but if I search "Zzz", it gives me the empty list.
This is known issue in the framework. https://github.com/flutter/flutter/issues/154532 It should be fixed in the next stable release.
There is a workaround by using a searchCallback.
searchCallback: (entries, query) {
if (query.isEmpty) {
return null;
}
final int index = entries.indexWhere(
(entry) => entry.label.toLowerCase().contains(query),
);
return index != -1 ? index : null;
},