Multi-Item Picker Componentin FlutterFlow

FlutterFlow is a powerful visual app builder that allows you to create fully functional mobile and web applications without writing extensive code. While it provides many built-in components, sometimes you need a more tailored solution. In this blog, we’ll walk you through the process of creating a custom multi-item picker widget in FlutterFlow.
Why a Multi-Item Picker?
A multi-item picker is essential when users need to select more than one option from a list. Common use cases include selecting interests, tags, categories, or filtering items in e-commerce and survey apps.
FlutterFlow doesn’t have a built-in multi-select component, but with the help of custom widgets, you can easily build one that integrates seamlessly into your app.
Step 1: Set Up Your Custom Widget in FlutterFlow
To start, create a new custom widget in FlutterFlow:
- Go to the Custom Code section in the left panel.
- Under Widgets, click + Add.
- Name it something like
MultiItemPickerComponent
. - Define the parameters:
items
(List, required): The list of all items to display.initialSelectedItems
(List, optional): The list of items that should appear pre-selected.title
(String, optional): Title of the picker UI.searchHintText
(String, optional): Placeholder for the search input field.width
,height
,maxHeight
(optional): For layout customization.
Step 2: Writing the Widget Code
Here’s a simplified version of a FlutterFlow-compliant widget (no function callbacks):
// Automatic FlutterFlow imports import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/custom_code/widgets/index.dart'; import '/flutter_flow/custom_functions.dart'; import 'package:flutter/material.dart'; // Begin custom widget code // DO NOT REMOVE OR MODIFY THE CODE ABOVE! class MultiItemPickerComponent extends StatefulWidget { const MultiItemPickerComponent({ Key? key, this.width, this.height, required this.items, this.initialSelectedItems, this.searchHintText = 'Search items...', this.title = 'Select Items', // this.buttonText = 'Done', this.maxHeight, }) : super(key: key); final double? width; final double? height; final double? maxHeight; final List<String> items; final List<String>? initialSelectedItems; final String searchHintText; final String title; // final String buttonText; @override _MultiItemPickerComponentState createState() => _MultiItemPickerComponentState(); } class _MultiItemPickerComponentState extends State<MultiItemPickerComponent> { final TextEditingController _searchController = TextEditingController(); List<String> _filteredItems = []; List<String> _selectedItems = []; @override void initState() { super.initState(); _filteredItems = widget.items; _selectedItems = widget.initialSelectedItems ?? []; _searchController.addListener(_filterItems); } @override void dispose() { _searchController.removeListener(_filterItems); _searchController.dispose(); super.dispose(); } void _filterItems() { final query = _searchController.text.toLowerCase(); setState(() { _filteredItems = widget.items .where((item) => item.toLowerCase().contains(query)) .toList(); }); } void _toggleItemSelection(String item) { setState(() { if (_selectedItems.contains(item)) { _selectedItems.remove(item); } else { _selectedItems.add(item); } }); } @override Widget build(BuildContext context) { return Container( width: widget.width ?? double.infinity, height: widget.height, constraints: BoxConstraints( maxHeight: widget.maxHeight ?? 400, ), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( blurRadius: 4, color: Color(0x33000000), offset: Offset(0, 2), ), ], ), child: Padding( padding: EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(widget.title, style: Theme.of(context).textTheme.titleMedium), Text('${_selectedItems.length} selected', style: Theme.of(context).textTheme.bodySmall), ], ), SizedBox(height: 12), TextFormField( controller: _searchController, decoration: InputDecoration( hintText: widget.searchHintText, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), prefixIcon: Icon(Icons.search), suffixIcon: _searchController.text.isNotEmpty ? InkWell( onTap: () { _searchController.clear(); }, child: Icon(Icons.clear), ) : null, ), ), SizedBox(height: 12), Text('Selected Items:', style: TextStyle(fontWeight: FontWeight.bold)), Wrap( spacing: 8, runSpacing: 8, children: _selectedItems.map((item) { return Chip( label: Text(item), onDeleted: () => _toggleItemSelection(item), ); }).toList(), ), SizedBox(height: 12), Text('Available Items:', style: TextStyle(fontWeight: FontWeight.bold)), Expanded( child: ListView.builder( itemCount: _filteredItems.length, itemBuilder: (context, index) { final item = _filteredItems[index]; final isSelected = _selectedItems.contains(item); return ListTile( title: Text(item), trailing: Icon( isSelected ? Icons.check_box : Icons.check_box_outline_blank, color: isSelected ? Theme.of(context).colorScheme.primary : null, ), onTap: () => _toggleItemSelection(item), ); }, ), ), SizedBox(height: 16), ], ), ), ); } }
Step 3: Use the Widget in Your UI
Now that your widget is added:
- Drag the
MultiItemPickerComponent
widget from the Custom Widgets tab. - Pass the
items
list and optionallyinitialSelectedItems
,title
, orsearchHintText
. - To retrieve selected items, bind the selected items to a local state or
AppState
variable usingActions
in FlutterFlow.
For example:
- On done/tap, update an
AppState
list variable with selected items using a custom action or logic.
Conclusion
With this custom widget, you now have a robust multi-item picker that works beautifully within the FlutterFlow environment. This approach offers flexibility, search capability, and a user-friendly interface.
This pattern — building custom widgets without callback parameters — can be reused for other advanced components. Happy building!
Feel free to connect with us:
And read more articles from FlutterDevs.com.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire Flutterflow developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! For any flutter-related queries, you can connect with us on Facebook, GitHub, Twitter, and LinkedIn.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.
