created clearing dropdown menus
This commit is contained in:
81
lib/widgets/clearing_dropdown_menu.dart
Normal file
81
lib/widgets/clearing_dropdown_menu.dart
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ClearingDropdownMenu<T> extends StatefulWidget {
|
||||||
|
final List<DropdownMenuEntry<T>> 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<ClearingDropdownMenu<T>> createState() =>
|
||||||
|
_ClearingDropdownMenuState<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ClearingDropdownMenuState<T> extends State<ClearingDropdownMenu<T>> {
|
||||||
|
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<T>(
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user