# 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. - [Basic Usage](#basic-usage) - [Constructor](#constructor) - [Props](#props) - [Layout Modes](#layout-modes) - [Event Handling](#event-handling) - [State Variants](#state-variants) - [Styling Examples](#styling-examples) - [All Supported Classes](#all-supported-classes) - [Customizing Theme](#customizing-theme) - [Related Documentation](#related-documentation) ```dart WFormSelect( 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( 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> options, ValueChanged? 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? values, String? Function(List?)? validator, void Function(List?)? onSaved, required List> options, ValueChanged>? 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>` | **Required** | The list of available options to display. | | `value` | `T?` | `null` | The currently selected value (single select). | | `values` | `List?` | `[]` | 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( 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( 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; }, ) ``` ## 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( 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. ```dart WFormMultiSelect( 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( 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 ) ``` ## Related Documentation - [WSelect - Core Dropdown Widget](./w-select.md) - [WFormInput - Validated Text Input](./w-form-input.md) - [WFormCheckbox - Validated Checkbox](./w-form-checkbox.md) - [Forms in Wind](../core-concepts/forms.md)