WFormSelect
A Wind-styled single or multi-select dropdown that integrates seamlessly with Flutter's Form validation. It wraps the core WSelect widget with FormField logic, providing labels, hint text, and automatic error state handling.
On this page
widgets/w_form_select
The live demo is not available for this example.
w_form_select.dart
View source
WFormSelect<String>(
label: 'Country',
placeholder: 'Select your country',
options: [
SelectOption(value: 'us', label: 'United States'),
SelectOption(value: 'uk', label: 'United Kingdom'),
],
className: 'w-full border rounded-lg error:border-red-500',
validator: (value) => value == null ? 'Please select a country' : null,
)
Basic Usage#
The WFormSelect (and its counterpart WFormMultiSelect) is designed to be used inside a Form widget. It automatically manages its own state and displays validation errors using the error: utility prefix when validation fails.
Form(
key: _formKey,
child: Column(
children: [
WFormSelect<String>(
value: _selectedValue,
options: myOptions,
onChange: (v) => setState(() => _selectedValue = v),
label: 'Select Category',
validator: (v) => v == null ? 'Required' : null,
),
WButton(
onTap: () {
if (_formKey.currentState!.validate()) {
// Process form
}
},
child: WText('Submit'),
),
],
),
)
Constructor#
WFormSelect#
WFormSelect({
Key? key,
T? value,
String? Function(T?)? validator,
void Function(T?)? onSaved,
AutovalidateMode? autovalidateMode,
bool enabled = true,
required List<SelectOption<T>> options,
ValueChanged<T?>? onChange,
String placeholder = 'Select an option',
String? className,
String? menuClassName,
bool searchable = false,
String? label,
String? hint,
bool showError = true,
// ... other WSelect props
})
WFormMultiSelect#
WFormMultiSelect({
Key? key,
List<T>? values,
String? Function(List<T>?)? validator,
void Function(List<T>?)? onSaved,
required List<SelectOption<T>> options,
ValueChanged<List<T>>? onMultiChange,
String placeholder = 'Select options',
String? label,
String? hint,
// ... other multi-select props
})
Props#
| Prop | Type | Default | Description |
|---|---|---|---|
className |
String? |
null |
Wind utility classes for the select trigger. |
options |
List<SelectOption<T>> |
Required | The list of available options to display. |
value |
T? |
null |
The currently selected value (single select). |
values |
List<T>? |
[] |
The currently selected values (multi select). |
label |
String? |
null |
Optional label text displayed above the select. |
hint |
String? |
null |
Optional hint text displayed below the select. |
validator |
String? Function(T?)? |
null |
Form validation logic. |
showError |
bool |
true |
Whether to display the error message when invalid. |
searchable |
bool |
false |
Enables a search input inside the dropdown. |
disabled |
bool |
false |
Disables user interaction. |
labelClassName |
String |
text-sm font-medium... |
Styling for the label text. |
errorClassName |
String |
text-red-500 text-xs... |
Styling for the error message. |
Layout Modes#
WFormSelect always uses a vertical flex-col layout to stack the label, the select trigger, and the error/hint text.
Standard Stack#
By default, the widget arranges elements in a clean vertical flow.
WFormSelect<String>(
label: 'Department',
hint: 'Choose your primary department',
options: departments,
className: 'border p-3 rounded-md',
)
Event Handling#
WFormSelect provides standard Form event handlers alongside the select-specific change callbacks.
WFormSelect<String>(
options: options,
onChange: (value) {
print('Selected: $value');
},
onSaved: (value) {
// Called when FormState.save() is invoked
_formData.dept = value;
},
validator: (value) {
if (value == null) return 'Selection required';
return null;
},
)
Accessibility#
The underlying WSelect trigger is one button named by its visible text: the selected option's label (labels joined with , for WFormMultiSelect), and the placeholder only while nothing is selected. Pass a translated placeholder in a localized app; the default is English.
State Variants#
Since WFormSelect injects the error state into the underlying WSelect, you can use the error: prefix to change the styling when validation fails.
WFormSelect<String>(
className: 'border-gray-300 focus:border-blue-500 error:border-red-500 error:bg-red-50',
options: options,
validator: (v) => v == null ? 'Error' : null,
)
Styling Examples#
Multi-Select Form Field#
The WFormMultiSelect variation handles lists of values and provides a different set of styling options for selected chips.
widgets/w_form_multiselect
The live demo is not available for this example.
w_form_multiselect.dart
View source
WFormMultiSelect<String>(
label: 'Interests',
values: _selectedInterests,
options: interestOptions,
className: 'border-2 rounded-xl p-2',
onMultiChange: (vals) => setState(() => _selectedInterests = vals),
validator: (vals) => vals!.isEmpty ? 'Select at least one' : null,
)
Searchable Form Select#
Perfect for long lists of options where users need to filter quickly.
WFormSelect<String>(
label: 'User',
searchable: true,
searchPlaceholder: 'Search by name...',
options: users,
className: 'w-full px-4 py-3 bg-white border',
)
All Supported Classes#
Since WFormSelect wraps WSelect, it supports all standard Wind utilities on the className and menuClassName props.
| Category | Classes |
|---|---|
| Sizing | w-full, max-w-md, h-12 |
| Spacing | p-{n}, px-{n}, py-{n}, m-{n} |
| Borders | border, rounded-{size}, ring-{n} |
| Colors | bg-{color}, text-{color}, border-{color} |
| States | hover:, focus:, disabled:, error: |
Customizing Theme#
You can globally customize the default styling of form labels and error messages through WindThemeData.
WindThemeData(
// Customizing default form select behavior via theme defaults
)