diff --git a/lib/src/widgets/reactive_dropdown_menu_field.dart b/lib/src/widgets/reactive_dropdown_menu_field.dart new file mode 100644 index 0000000..d8a8b20 --- /dev/null +++ b/lib/src/widgets/reactive_dropdown_menu_field.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +/// A reactive widget that wraps a [DropdownMenu]. +class ReactiveDropdownMenuField extends ReactiveFocusableFormField { + ReactiveDropdownMenuField({ + required List> dropdownMenuEntries, + super.key, + super.formControlName, + super.formControl, + super.focusNode, + super.validationMessages, + super.showErrors, + bool readOnly = false, + bool enabled = true, + Widget? label, + double? width, + double? menuHeight, + Widget? leadingIcon, + Widget? trailingIcon, + String? hintText, + String? helperText, + String? errorText, + Widget? selectedTrailingIcon, + bool enableFilter = false, + bool enableSearch = true, + TextStyle? textStyle, + TextAlign textAlign = TextAlign.start, + InputDecorationTheme? inputDecorationTheme, + MenuStyle? menuStyle, + TextEditingController? controller, + ValueChanged>? onSelected, + bool? requestFocusOnTap, + EdgeInsets? expandedInsets, + FilterCallback? filterCallback, + SearchCallback? searchCallback, + List? inputFormatters, + }) : super( + builder: (field) { + var effectiveValue = field.value; + if (effectiveValue != null && !dropdownMenuEntries.any((item) => item.value == effectiveValue)) { + effectiveValue = null; + } + + return DropdownMenu( + enabled: enabled, + width: width, + menuHeight: menuHeight, + leadingIcon: leadingIcon, + trailingIcon: trailingIcon, + label: label, + hintText: hintText, + helperText: helperText, + errorText: errorText, + selectedTrailingIcon: selectedTrailingIcon, + enableFilter: enableFilter, + enableSearch: enableSearch, + textStyle: textStyle, + textAlign: textAlign, + inputDecorationTheme: inputDecorationTheme, + menuStyle: menuStyle, + controller: controller, + initialSelection: effectiveValue, + onSelected: readOnly || field.control.disabled + ? null + : (value) { + field.didChange(value); + onSelected?.call(field.control); + }, + focusNode: field.focusNode, + requestFocusOnTap: requestFocusOnTap, + expandedInsets: expandedInsets, + filterCallback: filterCallback, + searchCallback: searchCallback, + dropdownMenuEntries: dropdownMenuEntries, + inputFormatters: inputFormatters, + ); + }, + ); +}