FormeAsyncInputChip<T extends Object> constructor
FormeAsyncInputChip<T extends Object> ({
- Key? key,
- String? name,
- List<
T> initialValue = const [], - FormeAsyncValidator<
List< ? asyncValidator,T> > - Duration? asyncValidatorDebounce,
- AutovalidateMode? autovalidateMode,
- FormeFieldDecorator<
List< ? decorator,T> > - bool enabled = true,
- FocusNode? focusNode,
- FormeFieldInitialized<
List< ? onInitialized,T> > - FormeFieldSetter<
List< ? onSaved,T> > - FormeFieldStatusChanged<
List< ? onStatusChanged,T> > - int? order,
- bool quietlyValidate = false,
- bool readOnly = false,
- bool requestFocusOnUserInteraction = true,
- FormeFieldValidationFilter<
List< ? validationFilter,T> > - FormeValidator<
List< ? validator,T> > - AutocompleteOptionToString<
T> displayStringForOption = RawAutocomplete.defaultStringForOption, - double optionsMaxHeight = 200,
- Duration? debounce,
- required FormeAsyncAutocompleteOptionsBuilder<
T> optionsBuilder, - FormeSearchCondition? searchCondition,
- FormeAsyncInputChipFieldViewBuilder<
T> ? fieldViewBuilder, - InputDecoration? fieldViewDecoration = const InputDecoration(),
- FormeFieldDecorator<
List< ? fieldViewdecorator,T> > - FormeAsyncInputChipBuilder<
T> ? inputChipBuilder, - FormeAsyncInputChipOptionsViewBuilder<
T> ? optionsViewBuilder, - InputDecoration? searchInputDecoration,
- double searchInputMinWidth = 50,
- double? searchInputStepWidth,
- WrapAlignment wrapAlignment = WrapAlignment.start,
- Clip wrapClipBehavior = Clip.none,
- WrapCrossAlignment wrapCrossAxisAlignment = WrapCrossAlignment.center,
- Axis wrapDirection = Axis.horizontal,
- WrapAlignment wrapRunAlignment = WrapAlignment.start,
- double wrapRunSpacing = 0.0,
- double wrapSpacing = 4.0,
- TextDirection? wrapTextDirection,
- VerticalDirection wrapVerticalDirection = VerticalDirection.down,
- EdgeInsets? fieldViewPadding = const EdgeInsets.symmetric(vertical: 8, horizontal: 6),
Implementation
FormeAsyncInputChip({
super.key,
super.name,
super.initialValue = const [],
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.displayStringForOption = RawAutocomplete.defaultStringForOption,
this.optionsMaxHeight = 200,
this.debounce,
required this.optionsBuilder,
this.searchCondition,
this.fieldViewBuilder,
this.fieldViewDecoration = const InputDecoration(),
this.fieldViewdecorator,
this.inputChipBuilder,
this.optionsViewBuilder,
this.searchInputDecoration,
this.searchInputMinWidth = 50,
this.searchInputStepWidth,
this.wrapAlignment = WrapAlignment.start,
this.wrapClipBehavior = Clip.none,
this.wrapCrossAxisAlignment = WrapCrossAlignment.center,
this.wrapDirection = Axis.horizontal,
this.wrapRunAlignment = WrapAlignment.start,
this.wrapRunSpacing = 0.0,
this.wrapSpacing = 4.0,
this.wrapTextDirection,
this.wrapVerticalDirection = VerticalDirection.down,
this.fieldViewPadding =
const EdgeInsets.symmetric(vertical: 8, horizontal: 6),
}) : super.allFields(
builder: (genericState) {
final FormeAsyncInputChipState<T> state =
genericState as FormeAsyncInputChipState<T>;
final bool readOnly = state.readOnly;
return RawAutocomplete<T>(
focusNode: state.focusNode,
textEditingController: state._textEditingController,
onSelected: (T t) {
state._add([t]);
},
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<T> onSelected, Iterable<T> options) {
SchedulerBinding.instance.addPostFrameCallback((timestamp) {
state._optionsViewVisibleStateNotifier.value = true;
});
void multiSelect(List<T> options) {
state._add(options);
}
return LayoutBuilder(builder: (context, constraints) {
final Size? size = state._fieldSizeGetter?.call();
final double? width = size?.width;
return optionsViewBuilder?.call(
state, context, multiSelect, state._options, width) ??
FormeMultiAutocompleteOptions(
displayStringForOption: displayStringForOption,
onSelected: multiSelect,
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.value, state,
state.effectiveController, focusNode, onSubmitted);
} else {
field = TextField(
enabled: state.enabled,
decoration: searchInputDecoration,
focusNode: focusNode,
controller: state.effectiveController,
readOnly: readOnly,
onSubmitted: readOnly
? null
: (v) {
onSubmitted();
},
);
field = Wrap(
direction: wrapDirection,
alignment: wrapAlignment,
runAlignment: wrapRunAlignment,
runSpacing: wrapRunSpacing,
spacing: wrapSpacing,
crossAxisAlignment: wrapCrossAxisAlignment,
textDirection: wrapTextDirection,
verticalDirection: wrapVerticalDirection,
clipBehavior: wrapClipBehavior,
children: state.value.map<Widget>((e) {
void onDeleted() {
state.delete(e);
}
if (inputChipBuilder != null) {
return inputChipBuilder(
e, state.readOnly ? null : onDeleted);
}
return InputChip(
label: Text(displayStringForOption(e)),
onDeleted: state.readOnly ? null : onDeleted,
);
}).toList()
..add(
IntrinsicWidth(
stepWidth: searchInputStepWidth,
child: Container(
constraints:
BoxConstraints(minWidth: searchInputMinWidth),
child: field,
),
),
),
);
}
final FormeFieldDecorator<List<T>>? finalDecorator =
fieldViewdecorator ??
(fieldViewDecoration == null
? null
: FormeInputDecorationDecorator(
childBuilder: (context, child) {
return Padding(
padding:
fieldViewPadding ?? EdgeInsets.zero,
child: child,
);
},
decorationBuilder: (context) =>
fieldViewDecoration,
emptyChecker: (value, state) {
return state.value.isEmpty &&
(state as FormeAsyncInputChipState<T>)
.effectiveController
.text
.isEmpty;
}));
field = finalDecorator == null
? field
: finalDecorator.build(context, field, state);
if (fieldViewBuilder == null) {
field = GestureDetector(
onTap: () {
final bool needFocus = !state.focusNode.hasFocus;
if (needFocus) {
state.focusNode.requestFocus();
}
if (state.focusNode.hasFocus && !kIsWeb) {
SystemChannels.textInput
.invokeMethod<Object>('TextInput.show');
}
},
child: field);
}
return _FieldView(state: state, child: field);
},
);
},
);