flutter-form-builder-ecosystem / form_builder_extra_fields

Additional ready-made form input fields for flutter_form_builder package
https://pub.dev/packages/form_builder_extra_fields
BSD 3-Clause "New" or "Revised" License
27 stars 47 forks source link

[FormBuilderSearchableDropdown] add multi selector #11

Open cedricDevWP opened 2 years ago

cedricDevWP commented 2 years ago

is it possible to use the multi selector feature?

WilliamCunhaCardoso commented 2 years ago

I believe you can try with manual building a field

YouSour commented 1 year ago

is it possible or not ? and any example how to add multi selector ?

deandreamatias commented 1 year ago

Not currently

YouSour commented 1 year ago

@deandreamatias noted

YouSour commented 1 year ago

anyone try with manual building a field with drop down package ? i try it everything fine but from builder current State value doesn't change here how i did :

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_extra_fields/form_builder_extra_fields.dart';
import '../../models/option_model.dart';

class FormBuilderSearchableDropdownMultiSelect extends StatefulWidget {
  final String name;
  final InputDecoration decoration;
  final Future<List<OptionModel>> Function(String)? onFind;
  final Widget Function(BuildContext, OptionModel, bool)? itemBuilder;
  final TextFieldProps searchFieldProps;
  final String noSelectedLabel;
  final double fontSize;
  final ValueChanged<List<String>>? selectedItem;
  final String submitButtonText;

  FormBuilderSearchableDropdownMultiSelect(
      {Key? key,
      required this.name,
      required this.decoration,
      required this.onFind,
      this.itemBuilder,
      this.searchFieldProps = const TextFieldProps(),
      this.noSelectedLabel = 'Select',
      this.fontSize = 16.0,
      this.selectedItem,
      this.submitButtonText = "SUBMIT"})
      : super(key: key);
  @override
  State<FormBuilderSearchableDropdownMultiSelect> createState() =>
      _FormBuilderSearchableDropdownMultiSelectState();
}

class _FormBuilderSearchableDropdownMultiSelectState
    extends State<FormBuilderSearchableDropdownMultiSelect> {
  final _popupCustomValidationKey =
      GlobalKey<DropdownSearchState<OptionModel>>();
  List<OptionModel> _selectedItems = [];

  void setFieldValue({required FormFieldState<dynamic> field}) {
    //set selected items to form builder state
    List<String> value = _selectedItems.map((e) => e.value.toString()).toList();
    if (widget.selectedItem != null) widget.selectedItem!(value);
    print(value);
    field.didChange(value);
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return FormBuilderField(
      name: widget.name,
      builder: (FormFieldState<dynamic> field) {
        return DropdownSearch<OptionModel>.multiSelection(
          key: _popupCustomValidationKey,
          asyncItems: widget.onFind,
          compareFn: (i, s) => i.value == s.value,
          dropdownDecoratorProps: DropDownDecoratorProps(
            dropdownSearchDecoration: widget.decoration,
          ),
          itemAsString: ((OptionModel? item) {
            return "${item!.label}";
          }),
          onChanged: (List<OptionModel> selectedItems) {
            setState(() {
              _selectedItems = selectedItems;
            });

            setFieldValue(field: field);
          },
          dropdownBuilder: (context, selectedItems) {
            return SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              padding: EdgeInsets.zero,
              child: selectedItems.isEmpty
                  ? Text(
                      widget.noSelectedLabel,
                      style: theme.textTheme.bodyText2!.copyWith(
                          color: theme.hintColor, fontSize: widget.fontSize),
                    )
                  : Row(
                      children: selectedItems
                          .map((item) => Padding(
                                padding: const EdgeInsets.only(right: 10.0),
                                child: InputChip(
                                  padding: EdgeInsets.zero,
                                  label: Text(selectedItems.isEmpty
                                      ? "Select"
                                      : item.label),
                                  onDeleted: () {
                                    _popupCustomValidationKey.currentState
                                        ?.removeItem(item);
                                    setState(() {
                                      _selectedItems = selectedItems;
                                    });
                                    setFieldValue(field: field);
                                  },
                                ),
                              ))
                          .toList()),
            );
          },
          popupProps: PopupPropsMultiSelection.dialog(
            isFilterOnline: true,
            showSelectedItems: true,
            showSearchBox: true,
            searchFieldProps: widget.searchFieldProps,
            itemBuilder: widget.itemBuilder,
            validationWidgetBuilder: (ctx, selectedItems) {
              return Padding(
                padding: const EdgeInsets.all(10.0),
                child: ElevatedButton(
                  child: Text(widget.submitButtonText),
                  style: ElevatedButton.styleFrom(
                    padding: EdgeInsets.all(20.0),
                  ),
                  onPressed: () {
                    _popupCustomValidationKey.currentState?.popupOnValidate();
                  },
                ),
              );
            },
          ),
        );
      },
    );
  }
}
WilliamCunhaCardoso commented 1 year ago

Can test one solution like this:

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormBuilderState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: FormBuilder(
          key: _formKey,
          child: Column(
            children: [
              FormBuilderDropdown(
                attribute: 'options',
                decoration: InputDecoration(labelText: 'Options'),
                hint: Text('Select options'),
                items: [
                  'Option 1',
                  'Option 2',
                  'Option 3',
                  'Option 4',
                ]
                  .map((option) => DropdownMenuItem(
                        value: option,
                        child: Text(option),
                      ))
                  .toList(),
                validators: [FormBuilderValidators.required()],
              ),
              SizedBox(height: 10),
              FormBuilderCheckboxList(
                attribute: 'options_checkbox',
                decoration: InputDecoration(labelText: 'Options Checkbox'),
                initialValue: ['Option 1'],
                options: [
                  FormBuilderFieldOption(
                    value: 'Option 1',
                    child: Text('Option 1'),
                  ),
                  FormBuilderFieldOption(
                    value: 'Option 2',
                    child: Text('Option 2'),
                  ),
                  FormBuilderFieldOption(
                    value: 'Option 3',
                    child: Text('Option 3'),
                  ),
                  FormBuilderFieldOption(
                    value: 'Option 4',
                    child: Text('Option 4'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

OBS: eu a gerei via Chat GPT. Infelizmente estou muito ocupado com o trabalho no momento

YouSour commented 1 year ago

@WilliamCunhaCardoso i need an example FormBuilderField implement with DropDownSearch package https://pub.dev/packages/dropdown_search

YouSour commented 1 year ago

any news about this ? i think it's very useful and important for app development.

WilliamCunhaCardoso commented 1 year ago

Unfortunately, I lack time due to my work. So, for now, I cannot implement it :/