DropdownButtonFormField2<T> constructor

DropdownButtonFormField2<T>({
  1. Key? key,
  2. Key? dropdownButtonKey,
  3. required List<DropdownMenuItem<T>>? items,
  4. DropdownButtonBuilder? selectedItemBuilder,
  5. T? value,
  6. Widget? hint,
  7. Widget? disabledHint,
  8. ValueChanged<T?>? onChanged,
  9. OnMenuStateChangeFn? onMenuStateChange,
  10. TextStyle? style,
  11. bool isDense = true,
  12. bool isExpanded = false,
  13. FocusNode? focusNode,
  14. bool autofocus = false,
  15. InputDecoration? decoration,
  16. FormFieldSetter<T>? onSaved,
  17. FormFieldValidator<T>? validator,
  18. AutovalidateMode? autovalidateMode,
  19. bool? enableFeedback,
  20. AlignmentGeometry alignment = AlignmentDirectional.centerStart,
  21. ButtonStyleData? buttonStyleData,
  22. IconStyleData iconStyleData = const IconStyleData(),
  23. DropdownStyleData dropdownStyleData = const DropdownStyleData(),
  24. MenuItemStyleData menuItemStyleData = const MenuItemStyleData(),
  25. DropdownSearchData<T>? dropdownSearchData,
  26. Widget? customButton,
  27. bool openWithLongPress = false,
  28. bool barrierDismissible = true,
  29. Color? barrierColor,
  30. String? barrierLabel,
})

Creates a DropdownButton2 widget that is a FormField, wrapped in an InputDecorator.

For a description of the onSaved, validator, or autovalidateMode parameters, see FormField. For the rest (other than decoration), see DropdownButton2.

The items, elevation, iconSize, isDense, isExpanded, autofocus, and decoration parameters must not be null.

Implementation

DropdownButtonFormField2({
  super.key,
  this.dropdownButtonKey,
  required List<DropdownMenuItem<T>>? items,
  DropdownButtonBuilder? selectedItemBuilder,
  T? value,
  Widget? hint,
  Widget? disabledHint,
  this.onChanged,
  OnMenuStateChangeFn? onMenuStateChange,
  TextStyle? style,
  bool isDense = true,
  bool isExpanded = false,
  FocusNode? focusNode,
  bool autofocus = false,
  InputDecoration? decoration,
  super.onSaved,
  super.validator,
  AutovalidateMode? autovalidateMode,
  bool? enableFeedback,
  AlignmentGeometry alignment = AlignmentDirectional.centerStart,
  ButtonStyleData? buttonStyleData,
  IconStyleData iconStyleData = const IconStyleData(),
  DropdownStyleData dropdownStyleData = const DropdownStyleData(),
  MenuItemStyleData menuItemStyleData = const MenuItemStyleData(),
  DropdownSearchData<T>? dropdownSearchData,
  Widget? customButton,
  bool openWithLongPress = false,
  bool barrierDismissible = true,
  Color? barrierColor,
  String? barrierLabel,
})  : assert(
        items == null ||
            items.isEmpty ||
            value == null ||
            items.where((DropdownMenuItem<T> item) {
                  return item.value == value;
                }).length ==
                1,
        "There should be exactly one item with [DropdownButton]'s value: "
        '$value. \n'
        'Either zero or 2 or more [DropdownMenuItem]s were detected '
        'with the same value',
      ),
      decoration = _getInputDecoration(decoration, buttonStyleData),
      super(
        initialValue: value,
        autovalidateMode: autovalidateMode ?? AutovalidateMode.disabled,
        builder: (FormFieldState<T> field) {
          final _DropdownButtonFormFieldState<T> state =
              field as _DropdownButtonFormFieldState<T>;
          final InputDecoration decorationArg = _getInputDecoration(decoration, buttonStyleData);
          final InputDecoration effectiveDecoration = decorationArg.applyDefaults(
            Theme.of(field.context).inputDecorationTheme,
          );

          final bool showSelectedItem = items != null &&
              items.where((DropdownMenuItem<T> item) => item.value == state.value).isNotEmpty;
          bool isHintOrDisabledHintAvailable() {
            final bool isDropdownDisabled = onChanged == null || (items == null || items.isEmpty);
            if (isDropdownDisabled) {
              return hint != null || disabledHint != null;
            } else {
              return hint != null;
            }
          }

          final bool isEmpty = !showSelectedItem && !isHintOrDisabledHintAvailable();

          // An unFocusable Focus widget so that this widget can detect if its
          // descendants have focus or not.
          return Focus(
            canRequestFocus: false,
            skipTraversal: true,
            child: Builder(
              builder: (BuildContext context) {
                return DropdownButtonHideUnderline(
                  child: DropdownButton2<T>._formField(
                    key: dropdownButtonKey,
                    items: items,
                    selectedItemBuilder: selectedItemBuilder,
                    value: state.value,
                    hint: hint,
                    disabledHint: disabledHint,
                    onChanged: onChanged == null ? null : state.didChange,
                    onMenuStateChange: onMenuStateChange,
                    style: style,
                    isDense: isDense,
                    isExpanded: isExpanded,
                    focusNode: focusNode,
                    autofocus: autofocus,
                    enableFeedback: enableFeedback,
                    alignment: alignment,
                    buttonStyleData: buttonStyleData,
                    iconStyleData: iconStyleData,
                    dropdownStyleData: dropdownStyleData,
                    menuItemStyleData: menuItemStyleData,
                    dropdownSearchData: dropdownSearchData,
                    customButton: customButton,
                    openWithLongPress: openWithLongPress,
                    barrierDismissible: barrierDismissible,
                    barrierColor: barrierColor,
                    barrierLabel: barrierLabel,
                    inputDecoration: effectiveDecoration.copyWith(errorText: field.errorText),
                    isEmpty: isEmpty,
                    isFocused: Focus.of(context).hasFocus,
                  ),
                );
              },
            ),
          );
        },
      );