import 'package:flutter/material.dart'; class ClearingDropdownMenu extends StatefulWidget { final List> entries; final T? initialValue; final void Function(T? item)? onSelected; final String? label; const ClearingDropdownMenu({ super.key, required this.entries, this.initialValue, this.onSelected, this.label, }); @override State> createState() => _ClearingDropdownMenuState(); } class _ClearingDropdownMenuState extends State> { late final TextEditingController _controller; final FocusNode _focusNode = FocusNode(); T? _selectedValue; @override void initState() { super.initState(); _selectedValue = widget.initialValue; _controller = TextEditingController( text: _selectedValue != null ? widget.entries .firstWhere((entry) => entry.value == _selectedValue) .label : ''); _focusNode.addListener(_onFocusChange); } void _onFocusChange() { if (!_focusNode.hasFocus) { // Check if the current text matches any entry final validEntry = widget.entries.any((entry) => entry.label.toLowerCase() == _controller.text.toLowerCase()); if (!validEntry) { // Clear the text and selection _controller.clear(); setState(() { _selectedValue = null; }); widget.onSelected?.call(null); } } } @override Widget build(BuildContext context) { return DropdownMenu( controller: _controller, focusNode: _focusNode, initialSelection: widget.initialValue, onSelected: (T? value) { setState(() { _selectedValue = value; }); widget.onSelected?.call(value); }, dropdownMenuEntries: widget.entries, label: widget.label != null ? Text(widget.label!) : null, ); } @override void dispose() { _controller.dispose(); _focusNode.dispose(); super.dispose(); } }