Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change state widget for go up data into main form #72

Closed
darkomenx opened this issue Mar 7, 2024 · 4 comments
Closed

change state widget for go up data into main form #72

darkomenx opened this issue Mar 7, 2024 · 4 comments
Labels
question Further information is requested

Comments

@darkomenx
Copy link

Hi Multiselect-dropdown,

First, thank you for your widget and your work. It seems to be very good and useful widget.
But I'm struggle for using this into form.

I try lot of thing for achieve to send data to main form widget (extends FormField, add the main form key from the parent to child, create new form key for this child) without result.

Now I fund a good way with creating this widget wrapped by FormBuilderField (package : flutter_form_builder).
I can send data to the parent form with state widget.

BUT MY ISSUE : I can't change the state of this widget.

I try to use "onOptionSelected" option to change my state but it seems that is not the good place to do this.

In context of this implementation of your widget :

`class MultiselectDropdownForm extends StatefulWidget
{
const MultiselectDropdownForm({super.key});

@OverRide
State createState() => MultiselectDropdownFormState();
}

class MultiselectDropdownFormState extends State
{
final OperationRepository operationRepository = getIt();
String? initialValue = 'tyty';

@override
Widget build(BuildContext context)
{
    return FormBuilderField
    (
        name: 'dfezdze',
        initialValue: initialValue,
        builder: (FormFieldState<String> field)
        {
            return FutureBuilder
            (
                future: getData(),
                builder: (context, snapshot)
                {
                    if (snapshot.connectionState == ConnectionState.done)
                    {
                        if (snapshot.data != null)
                        {
                            List<String> assignments = snapshot.data!;

                            return MultiSelectDropDown
                            (
                                options: [for (var assign in assignments) ValueItem(label: assign, value: assign)],
                                selectionType: SelectionType.multi,
                                chipConfig: const ChipConfig(wrapType: WrapType.wrap),
                                dropdownHeight: 300,
                                optionTextStyle: const TextStyle(fontSize: 12),
                                selectedOptionIcon: const Icon(Icons.check_circle),
                                onOptionSelected: (List<ValueItem<String>> selectedOptions) {

                                    setState(() {
                                        initialValue = 'toto';
                                    });

                                    print(initialValue);
                                    initialValue = 'toto';
                                    print(initialValue);
                                },
                            );
                        }
                    },
            );
        },
    );
}

}`

The value 'tyty' is always sended to the main Form by the widget and never change by the 'toto' value.
The main Form needs to read the state of the multiselect widget but this state not change during the handling.

If I try to write a setState() statement into "onOptionSelected" options it throws this error :

`======== Exception caught by scheduler library =====================================================
The following assertion was thrown during a scheduler callback:
setState() called after dispose(): OverlayState#5187b(lifecycle state: defunct, entries: [OverlayEntry#c558a(opaque: true; maintainState: false), OverlayEntry#ab89e(opaque: false; maintainState: true), OverlayEntry#8ad34(opaque: false; maintainState: false), OverlayEntry#f3b12(opaque: false; maintainState: true)])

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.

The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

When the exception was thrown, this was the stack:
0 State.setState. (package:flutter/src/widgets/framework.dart:1167:9)
1 State.setState (package:flutter/src/widgets/framework.dart:1202:6)
2 OverlayState._markDirty (package:flutter/src/widgets/overlay.dart:762:7)
3 OverlayEntry.remove. (package:flutter/src/widgets/overlay.dart:218:17)
4 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
5 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1322:11)
6 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
7 _invoke (dart:ui/hooks.dart:312:13)`

Resume :

How can I retrieve my data multiselect into the main Form that wrap this widget please ?

@oi-narendra
Copy link
Owner

Since you are using FormBuilderField, you should use fieldDidChange method of that field.

In your case, it should be something like this.

 onOptionSelected: (List<ValueItem<String>> selectedOptions) {

     field.didChange(selectedOptions.first.value);

} 

@oi-narendra oi-narendra added the question Further information is requested label Mar 10, 2024
@darkomenx
Copy link
Author

unfortunetely I already try this and that produce this error :

======== Exception caught by scheduler library =====================================================
The following assertion was thrown during a scheduler callback:
setState() called after dispose(): OverlayState#e100c(lifecycle state: defunct, entries: [OverlayEntry#a6473(opaque: true; maintainState: false), OverlayEntry#1bb51(opaque: false; maintainState: true), OverlayEntry#63b36(opaque: false; maintainState: false), OverlayEntry#75e18(opaque: false; maintainState: true)])

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.

The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

If I add the mounted this like this the issue is the same like before :

 if (context.mounted)
 {
         field.didChange(selectedOptions.first.value);
        // OR
        setState(() { initialValue = 'foobar'; });
 }

@oi-narendra
Copy link
Owner

Check Beta version.

@oi-narendra
Copy link
Owner

Migrate to the latest version v3.0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants