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!
From Our Parent Company Aeologic
Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.
Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.
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.
