WSelect
A highly customizable, utility-first select component that supports single selection, multi-selection, searching, and remote data fetching.
- Basic Usage
- Constructor
- Props
- Layout Modes
- Event Handling
- State Variants
- Styling Examples
- All Supported Classes
- Customizing Theme
- Related Documentation
WSelect(
value: _selected,
options: [
SelectOption(value: 'dart', label: 'Dart'),
SelectOption(value: 'flutter', label: 'Flutter'),
],
onChange: (value) => setState(() => _selected = value),
className: 'w-64 bg-white border border-gray-300 rounded-lg',
)
Basic Usage
The WSelect widget replaces the standard Material Dropdown with a utility-first approach. It manages its own open state while providing a controlled interface for selection.
WSelect(
placeholder: 'Choose a number',
options: List.generate(5, (i) => SelectOption(value: i, label: 'Option $i')),
onChange: (val) => print('Selected: $val'),
className: 'bg-white border p-3 rounded-md',
)
Constructor
const WSelect({
Key? key,
T? value,
ValueChanged? onChange,
bool isMulti = false,
List? values,
ValueChanged>? onMultiChange,
SelectedChipBuilder? selectedChipBuilder,
required List> options,
bool searchable = false,
Future>> Function(String)? onSearch,
String searchPlaceholder = 'Search...',
Future> Function(String)? onCreateOption,
CreateOptionBuilder? createOptionBuilder,
Future>> Function()? onLoadMore,
bool hasMore = false,
String? className,
String? menuClassName,
String placeholder = 'Select an option',
bool disabled = false,
double? menuWidth,
double maxMenuHeight = 300,
Set? states,
SelectTriggerBuilder? triggerBuilder,
MultiSelectTriggerBuilder? multiTriggerBuilder,
SelectItemBuilder? itemBuilder,
EmptyStateBuilder? emptyBuilder,
LoadingBuilder? loadingBuilder,
})
Props
| Prop | Type | Default | Description |
|---|---|---|---|
className |
String? |
null |
Utility classes for the trigger container |
menuClassName |
String? |
null |
Utility classes for the dropdown menu |
options |
List |
Required | List of items to display |
value |
T? |
null |
Selected value in single-select mode |
onChange |
ValueChanged |
null |
Callback for single selection changes |
isMulti |
bool |
false |
Enables multi-select mode |
values |
List |
null |
Selected values in multi-select mode |
onMultiChange |
ValueChanged |
null |
Callback for multi-selection changes |
searchable |
bool |
false |
Shows a search input in the menu |
searchPlaceholder |
String |
'Search...' |
Placeholder text in the search input |
onSearch |
Future |
null |
Async remote search handler; returns filtered options for the query |
onCreateOption |
Future |
null |
Tagging handler; called when the user creates a new option from search input |
createOptionBuilder |
CreateOptionBuilder? |
null |
Custom builder for the "create new option" row in the menu |
onLoadMore |
Future |
null |
Pagination handler; called when the user scrolls past the current list |
hasMore |
bool |
false |
When true, indicates more pages are available for onLoadMore |
placeholder |
String |
'Select an option' |
Text shown when no value is selected |
disabled |
bool |
false |
Prevents interaction |
menuWidth |
double? |
null |
Fixed dropdown width; defaults to the trigger width |
maxMenuHeight |
double |
300 |
Maximum height of the dropdown list |
states |
Set |
null |
Custom states for dynamic styling |
triggerBuilder |
SelectTriggerBuilder |
null |
Custom trigger renderer for single-select |
multiTriggerBuilder |
MultiSelectTriggerBuilder |
null |
Custom trigger renderer for multi-select |
selectedChipBuilder |
SelectedChipBuilder |
null |
Custom chip renderer for selected items in multi-select |
itemBuilder |
SelectItemBuilder |
null |
Custom renderer for each option in the menu |
emptyBuilder |
EmptyStateBuilder? |
null |
Custom widget when no options match the search |
loadingBuilder |
LoadingBuilder? |
null |
Custom widget shown while onSearch or onLoadMore is pending |
Layout Modes
Single Select
The default mode for selecting a single item. It displays the label of the selected option in the trigger.
WSelect(
value: 'apple',
options: [
SelectOption(value: 'apple', label: 'Apple'),
SelectOption(value: 'banana', label: 'Banana'),
],
onChange: (v) => print(v),
)
Multi Select
Enable isMulti: true to allow multiple selections. By default, it displays selected items as chips.
WSelect(
isMulti: true,
values: ['red', 'blue'],
options: [
SelectOption(value: 'red', label: 'Red'),
SelectOption(value: 'blue', label: 'Blue'),
SelectOption(value: 'green', label: 'Green'),
],
onMultiChange: (list) => print(list),
)
Event Handling
WSelect provides callbacks for selection changes and remote interactions.
WSelect(
onChange: (value) {
// Handle single selection
},
onSearch: (query) async {
// Return list of options based on search query
return fetchRemoteOptions(query);
},
onLoadMore: () async {
// Load next page of options
return fetchNextPage();
},
)
State Variants
WSelect automatically manages several states that you can style using prefixes in className:
hover:- When the mouse is over the trigger.focus:- When the dropdown is open.disabled:- When the widget is disabled.selected:- When a value is selected.
WSelect(
className: 'border-gray-300 hover:border-blue-500 focus:ring-2 focus:ring-blue-200',
)
Styling Examples
Searchable Select
Combine searchable: true with custom menu styling for a robust selection experience.
WSelect(
searchable: true,
searchPlaceholder: 'Search countries...',
menuClassName: 'bg-white shadow-xl rounded-xl border border-gray-100',
options: countries,
onChange: (val) => _country = val,
)
Tagging (Create Option)
Allow users to create new options if a search yields no results.
WSelect(
searchable: true,
onCreateOption: (query) async {
final newOpt = SelectOption(value: query.toLowerCase(), label: query);
// Add to your local state/database
return newOpt;
},
options: existingTags,
)
All Supported Classes
| Category | Classes |
|---|---|
| Layout | flex, hidden, w-{size}, h-{size} |
| Spacing | p-{n}, m-{n}, gap-{n} |
| Visuals | bg-{color}, border, rounded, shadow |
| States | hover:, focus:, disabled:, dark: |
| Custom | open:, selected: |
Customizing Theme
The default styling for WSelect and its chips can be influenced by the WindThemeData.
WindThemeData(
colors: {
'primary': Colors.indigo,
},
)
Related Documentation
- WFormSelect - Form-integrated version with validation
- WPopover - The underlying overlay engine
- WInput - Used for the internal search field