Skip to Content
Forui 0.15.0 is released 🎉
DocumentationFormMulti Select

Multi Select

A multi select displays a list of drop-down options for the user to pick from.

It is a form-field and can therefore be used in a form.

For single selections, consider using a select.

For touch devices, a select tile group or select menu tile is generally recommended over this.

CLI

To generate and customize this style:

dart run forui style create multi-select

Usage

FMultiSelect(...)

FMultiSelect<Locale>( items: { 'United States': Locale('en', 'US'), 'Canada': Locale('en', 'CA'), 'Japan': Locale('ja', 'JP'), }, controller: FMultiSelectController<Locale>(vsync: this, min: 1, max: 2), style: FMultiSelectStyle.inherit(...), label: const Text('Country'), description: const Text('Select your country of residence'), hint: Text('Choose a country'), keepHint: true, format: (value) => Text(value.toUpperCase()), sort: (a, b) => a.compareTo(b), onChange: (value) => print('Selected country: $value'), onSaved: (value) => print('Saved country: $value'), autovalidateMode: AutovalidateMode.onUserInteraction, prefixBuilder: (context, styles) => Icon(FIcons.globe), suffixBuilder: (context, styles) => Icon(FIcons.arrowDown), tagBuilder: (context, controller, styles, value, label) => FMultiSelectTag(label: label), popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400), clearable: true, contentScrollHandles: true, min: 1, max: 2, initialValue: {Locale('en', 'US')}, );

FMultiSelect.rich(...)

FMultiSelect<String>.rich( controller: FMultiSelectController<String>(vsync: this, min: 1, max: 2), style: FMultiSelectStyle(...), label: const Text('Country'), description: const Text('Select your country of residence'), hint: Text('Choose a country'), keepHint: true, format: (value) => Text(value.toUpperCase()), sort: (a, b) => a.compareTo(b), onChange: (value) => print('Selected country: $value'), onSaved: (value) => print('Saved country: $value'), autovalidateMode: AutovalidateMode.onUserInteraction, prefixBuilder: (context, styles) => Icon(FIcons.globe), suffixBuilder: (context, styles) => Icon(FIcons.arrowDown), tagBuilder: (context, controller, styles, value, label) => FMultiSelectTag( label: label), popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400), clearable: true, contentDivider: FItemDivider.none, contentScrollHandles: true, min: 1, max: 2, initialValue: {'ca'}, children: [ FSelectSection.rich( label: const Text('North American Countries'), divider: FItemDivider.none, children: [ FSelectItem( title: const Text('United States'), value: 'us'), FSelectItem(title: Text('Canada'), value: 'ca'), ], ), FSelectItem(title: Text('Japan'), value: 'jp'), ], );

FMultiSelect.search(...)

FMultiSelect<User>.search( items: { 'Bob Ross': User(firstName: 'Bob', lastName: 'Ross'), 'John Doe': User(firstName: 'John', lastName: 'Doe'), 'Mary Jane': User(firstName: 'Mary', lastName: 'Jane'), 'Peter Parker': User(firstName: 'Peter', lastName: 'Parker'), }, controller: FMultiSelectController<User>(vsync: this, min: 1, max: 2), style: FMultiSelectStyle.inherit(...), label: const Text('User'), description: const Text('Search and select a user'), format: (user) => Text('${user.firstName} ${user.lastName}'), sort: (a, b) => a.compareTo(b), hint: Text('Search users...'), popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400), clearable: true, onChange: (value) => print('Selected country: $value'), tagBuilder: (context, controller, styles, value, label) => FMultiSelectTag( label: label), min: 1, max: 2, initialValue: {'value'}, contentDivider: FItemDivider.none, contentScrollHandles: false, contentPhysics: const BouncingScrollPhysics(), contentEmptyBuilder: (context, style) => Text('No results'), filter: (query) async { // Fetch users based on search query return fetchUsers(query); }, contentBuilder: (context, _, users) => [ for (final user in users) FSelectItem(title: Text('${user.firstName} ${user.lastName}'), value: user), ], searchFieldProperties: FSelectSearchFieldProperties( autofocus: true, hint: 'Type to search...', ), contentLoadingBuilder: (context, style) => Text('Loading...'), contentErrorBuilder: (context, error, stackTrace) => Text('Error...'), );

FMultiSelect.searchBuilder(...)

FMultiSelect<User>.search( controller: FMultiSelectController<User>(vsync: this, min: 1, max: 2), style: FMultiSelectStyle.inherit(...), label: const Text('User'), description: const Text('Search and select a user'), format: (user) => Text('${user.firstName} ${user.lastName}'), sort: (a, b) => a.compareTo(b), hint: Text('Search users...'), tagBuilder: (context, controller, styles, value, label) => FMultiSelectTag( label: label), popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400), clearable: true, onChange: (value) => print('Selected country: $value'), min: 1, max: 2, initialValue: {'value'}, contentDivider: FItemDivider.none, contentScrollHandles: false, contentPhysics: const BouncingScrollPhysics(), contentEmptyBuilder: (context, style) => Text('No results'), filter: (query) async { // Fetch users based on search query return fetchUsers(query); }, contentBuilder: (context, _, users) => [ for (final user in users) FSelectItem(title: Text('${user.firstName} ${user.lastName}'), value: user), ], searchFieldProperties: FSelectSearchFieldProperties( autofocus: true, hint: 'Type to search...', ), contentLoadingBuilder: (context, style) => Text('Loading...'), contentErrorBuilder: (context, error, stackTrace) => Text('Error...'), );

Examples

Detailed

Sections

Dividers

Searchable

Sync

Async

Async with Custom Loading

Async with Custom Error Handling

Behavior

Clearable

Custom Formatting

Min & Max

With Scroll Handles

Sorted

Form

Last updated on