Skip to content

WFormSelect

View raw .md

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
Preview widgets/w_form_select The live demo is not available for this example. w_form_select.dart View source
dart
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.

dart
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#

dart
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#

dart
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.

dart
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.

dart
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.

dart
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.

Preview widgets/w_form_multiselect The live demo is not available for this example. w_form_multiselect.dart View source
dart
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.

dart
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.

dart
WindThemeData(
  // Customizing default form select behavior via theme defaults
)
esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.