FormeAsyncAutocomplete<T extends Object> constructor

FormeAsyncAutocomplete<T extends Object>({
  1. Key? key,
  2. String? name,
  3. T? initialValue,
  4. FormeAsyncValidator<T?>? asyncValidator,
  5. Duration? asyncValidatorDebounce,
  6. AutovalidateMode? autovalidateMode,
  7. FormeFieldDecorator<T?>? decorator,
  8. bool enabled = true,
  9. FocusNode? focusNode,
  10. FormeFieldInitialized<T?>? onInitialized,
  11. FormeFieldSetter<T?>? onSaved,
  12. FormeFieldStatusChanged<T?>? onStatusChanged,
  13. int? order,
  14. bool quietlyValidate = false,
  15. bool readOnly = false,
  16. bool requestFocusOnUserInteraction = true,
  17. FormeFieldValidationFilter<T?>? validationFilter,
  18. FormeValidator<T?>? validator,
  19. double optionsMaxHeight = 200,
  20. Duration? debounce,
  21. required FormeAsyncAutocompleteOptionsBuilder<T> optionsBuilder,
  22. FormeSearchCondition? searchCondition,
  23. FormeFieldDecorator<T?>? fieldViewDecorator,
  24. AutocompleteOptionToString<T> displayStringForOption = RawAutocomplete.defaultStringForOption,
  25. InputDecoration? decoration = const InputDecoration(),
  26. AutocompleteFieldViewBuilder? fieldViewBuilder,
  27. FormeAutocompleteOptionsViewBuilder<T>? optionsViewBuilder,
})

Implementation

FormeAsyncAutocomplete({
  super.key,
  super.name,
  super.initialValue,
  super.asyncValidator,
  super.asyncValidatorDebounce,
  super.autovalidateMode,
  super.decorator,
  super.enabled = true,
  super.focusNode,
  super.onInitialized,
  super.onSaved,
  super.onStatusChanged,
  super.order,
  super.quietlyValidate = false,
  super.readOnly = false,
  super.requestFocusOnUserInteraction = true,
  super.validationFilter,
  super.validator,
  this.optionsMaxHeight = 200,
  this.debounce,
  required this.optionsBuilder,
  this.searchCondition,
  this.fieldViewDecorator,
  this.displayStringForOption = RawAutocomplete.defaultStringForOption,
  InputDecoration? decoration = const InputDecoration(),
  this.fieldViewBuilder,
  this.optionsViewBuilder,
}) : super.allFields(
        builder: (genericState) {
          final FormeAsyncAutocompleteState<T> state =
              genericState as FormeAsyncAutocompleteState<T>;
          final bool readOnly = state.readOnly;
          return RawAutocomplete<T>(
            focusNode: state.focusNode,
            textEditingController: state._textEditingController,
            onSelected: (T t) {
              state.didChange(t);
              state.effectiveController.selection = TextSelection.collapsed(
                  offset: state.effectiveController.text.length);
              state._clearOptionsAndWaiting();
            },
            optionsViewBuilder: (BuildContext context,
                AutocompleteOnSelected<T> onSelected, Iterable<T> options) {
              state._optionsViewVisibleStateNotifier.value = true;

              return LayoutBuilder(builder: (context, constraints) {
                final Size? size = state._fieldSizeGetter?.call();
                final double? width = size?.width;
                return optionsViewBuilder?.call(
                        context, onSelected, state._options, width) ??
                    AutocompleteOptions(
                      displayStringForOption: displayStringForOption,
                      onSelected: onSelected,
                      options: state._options,
                      maxOptionsHeight: optionsMaxHeight,
                      width: width,
                    );
              });
            },
            optionsBuilder: (TextEditingValue value) {
              if (state._stateNotifier.value ==
                  FormeAsyncOperationState.success) {
                return state._options;
              }
              return const Iterable.empty();
            },
            displayStringForOption: displayStringForOption,
            fieldViewBuilder:
                (context, textEditingController, focusNode, onSubmitted) {
              Widget field;
              if (fieldViewBuilder != null) {
                field = fieldViewBuilder(context, state.effectiveController,
                    focusNode, onSubmitted);
              } else {
                field = TextField(
                  enabled: state.enabled,
                  onSubmitted: readOnly
                      ? null
                      : (v) {
                          onSubmitted();
                        },
                  decoration: decoration?.copyWith(
                      errorText: state.errorText,
                      suffixIcon: decoration.suffixIcon ??
                          Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              ValueListenableBuilder<
                                      FormeAsyncOperationState?>(
                                  valueListenable: state._stateNotifier,
                                  builder: (context, state, child) {
                                    if (state == null) {
                                      return const SizedBox.shrink();
                                    }
                                    switch (state) {
                                      case FormeAsyncOperationState
                                          .processing:
                                        return const Padding(
                                          padding: EdgeInsets.all(0),
                                          child: SizedBox(
                                            height: 16,
                                            width: 16,
                                            child: CircularProgressIndicator(
                                              strokeWidth: 3,
                                            ),
                                          ),
                                        );
                                      case FormeAsyncOperationState.success:
                                        return const SizedBox.shrink();
                                      case FormeAsyncOperationState.error:
                                        return const Icon(Icons.dangerous,
                                            color: Colors.redAccent);
                                    }
                                  }),
                            ],
                          )),
                  focusNode: focusNode,
                  controller: state.effectiveController,
                  onChanged: readOnly
                      ? null
                      : (String v) {
                          final T? value = state.value;
                          if (value != null &&
                              displayStringForOption(value) != v) {
                            state.didChange(null);
                          }
                        },
                );
              }
              return _FieldView(
                  state: state,
                  child: fieldViewDecorator == null
                      ? field
                      : fieldViewDecorator.build(
                          context,
                          field,
                          state,
                        ));
            },
          );
        },
      );