Select and multi-select
A dropdown over a single-select controller, and a chip group over a multi-select one, both with a label and an error slot.
Both controllers carry their options, so the widget only asks the field what to list and what is selected. An
InputDecorator gives either widget a label and an errorText, and — unlike a form-field dropdown seeded with an
initial value — always reflects the field's current value, including after reset().
Source3 files
class _DropdownInput<V> extends StatelessWidget {
const _DropdownInput({required this.field, required this.label});
final AdvancedSingleSelectFieldController<V, String> field;
final String label;
@override
Widget build(BuildContext context) {
return AdvancedFieldBuilder<V?, String>(
field: field,
builder: (context, state, _) => Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: InputDecorator(
decoration: InputDecoration(labelText: label, errorText: state.error),
isEmpty: state.value == null,
child: DropdownButtonHideUnderline(
child: DropdownButton<V>(
value: state.value,
isExpanded: true,
isDense: true,
focusNode: field.focusNode,
items: [
for (final option in field.options)
DropdownMenuItem(value: option, child: Text('$option')),
],
onChanged: state.readOnly ? null : field.select,
),
),
),
),
);
}
}DocsActions is a shorthand these docs define, not part of the package. See Rendering fields for the widget code an app writes.field.select(option) and field.toggleElement(option) are the setters; both are no-ops while read-only, which is why
the widgets null their callbacks on state.readOnly rather than calling getValueSetter(). select asserts in debug
builds that the option is one of options; select(null) clears and is always allowed.
DropdownButtonFormField and Flutter versions
Its selected-value parameter is value: up to Flutter 3.33 and initialValue: from 3.35 on. DropdownButton inside
an InputDecorator, as above, compiles on every version.