selectByName method
Programmatically selects an item matching name.
For async dropdowns: does a targeted API search by name first (large page),
then falls back to the already-loaded items list.
For sync dropdowns: searches the provided items list.
Returns true if an item was found and selected.
Implementation
@override
Future<bool> selectByName(String name) async {
T? _findMatch() {
// Exact match first, then partial
for (final item in items) {
if (valueToShow(item).toLowerCase() == name.toLowerCase()) return item;
}
for (final item in items) {
if (valueToShow(item).toLowerCase().contains(name.toLowerCase())) return item;
}
return null;
}
// For async dropdowns: targeted API search with large page size FIRST
if (asyncSearchCallback != null && searchColumn != null) {
try {
loading = true;
notifyListeners();
final (values, _) = await asyncSearchCallback!(
page: 1,
perPage: 100,
searchBy: {searchColumn!: name},
);
items = values;
} catch (_) {
// keep whatever was already loaded
} finally {
loading = false;
notifyListeners();
}
final match = _findMatch();
if (match != null) {
_selectItem(match);
return true;
}
// Secondary fallback: load first page unfiltered in case the name is partial
try {
loading = true;
notifyListeners();
final (values, _) = await asyncSearchCallback!(page: 1, perPage: 100);
items = values;
} catch (_) {
// ignore
} finally {
loading = false;
notifyListeners();
}
final fallbackMatch = _findMatch();
if (fallbackMatch != null) {
_selectItem(fallbackMatch);
return true;
}
return false;
}
// Sync dropdown: load items if empty, then match locally
if (items.isEmpty && syncSearchCallback != null) {
items = await syncSearchCallback!('');
}
final match = _findMatch();
if (match != null) {
_selectItem(match);
return true;
}
return false;
}