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

Update an Open Dropdown Menu #101

Closed
cody1024d opened this issue Nov 15, 2022 · 8 comments
Closed

Update an Open Dropdown Menu #101

cody1024d opened this issue Nov 15, 2022 · 8 comments
Labels
enhancement New feature or request

Comments

@cody1024d
Copy link

cody1024d commented Nov 15, 2022

Right now I'm putting together a hacky solution using the search functionality provided in this framework.

However, overall, I'd like the ability to dynamically update the dropdown menu items on a dropdown that's open.

My use case is as follows:

When the user first taps on the dropdown, we make an async call to get the items. While this call is occurring I show a single item, that represents the loading state. Once these items have been fetched, I'd like to push them into the already open menu. As of right now, I don't think there's a way to update the state of the DropDownMenu, besides hacking together something with the search controller (which is what I'm going to do)

Edit: My hack unfortunately doesn't even work either :( This is because the searchController only goes through the items on the DropDownRoute, which is not updated with the latest items either

@AhmedLSayed9 AhmedLSayed9 added the enhancement New feature or request label Nov 16, 2022
@cody1024d
Copy link
Author

@AhmedLSayed9 Would this be something you'd be open to PRs for? And if so, do you have any high-level direction/location you'd want to put this?

It should be fairly straight-forward; as you could check for something in didUpdateWidget?

@AhmedLSayed9
Copy link
Owner

Sure, give it a try.
I think it's more difficult than that, check _handleTap() method.
I think we need ValueListenableBuilder to achieve this.

@AhmedLSayed9
Copy link
Owner

AhmedLSayed9 commented Nov 17, 2022

This is a hacky solution for now that auto re-open the dropdown menu in milliseconds:

  final dropdownKey = GlobalKey<DropdownButton2State>();
  bool _isOpen = false;

  List<String>? items;
  String? selectedValue;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DropdownButtonHideUnderline(
          child: DropdownButton2(
            key: dropdownKey,
            hint: Text(
              'Select Item',
              style: TextStyle(
                fontSize: 14,
                color: Theme.of(context).hintColor,
              ),
            ),
            onMenuStateChange: (bool isOpen) async {
              _isOpen = isOpen;
              if (isOpen && items == null) {
                //Simulate api call delay to show loading for 3 seconds
                await Future.delayed(const Duration(seconds: 3));
                setState(() {
                  items = [
                    'Item1',
                    'Item2',
                    'Item3',
                    'Item4',
                  ];
                });

                //Return if the user already closed the menu
                if (!_isOpen) return;

                Navigator.of(context).pop();
                //await removeDropdownRoute to avoid _dropdownRoute != null Exception
                await Future.delayed(const Duration(milliseconds: 100));
                //Re-open the menu programmatically
                dropdownKey.currentState!.callTap();
              }
            },
            items: items == null
                ? [
                    const DropdownMenuItem<String>(
                      enabled: false,
                      child: Center(
                        child: CircularProgressIndicator(),
                      ),
                    ),
                  ]
                : items!
                    .map((item) => DropdownMenuItem<String>(
                          value: item,
                          enabled: false,
                          child: Text(
                            item,
                            style: const TextStyle(
                              fontSize: 14,
                            ),
                          ),
                        ))
                    .toList(),
            value: selectedValue,
            onChanged: (value) {
              setState(() {
                selectedValue = value as String;
              });
            },
            buttonHeight: 40,
            buttonWidth: 140,
          ),
        ),
      ),
    );
  }
Screen.Recording.2022-11-17.at.5.47.33.PM.mov

@cody1024d
Copy link
Author

cody1024d commented Nov 22, 2022

Thank you for that @AhmedLSayed9 . Unfortunately; I have another wrench to throw into things -- I'm using the DropdownButtonFormField2; and so it's state is not DropDownButton2State, which complicates me calling callTap().

EDIT: To make the above possible with the formfield; could you, instead of passing the key into the actual formField widget, instead pass it into the wrapped-widget that you create? This way the key still coincides with the actual instance of the DropDown widget. I'm not 100% sure on the other ramifications of this, though. Although if all DropdownButtonFormFields wrap around the DropDownButton widgets, the uniqueness of keys should still hold (although it does seem a bit un-intuitive for future developers that the key provided is used by a child widget and not the constructed widget)

@AhmedLSayed9
Copy link
Owner

You can use dropdownButtonKey property now in v1.9.1
I think a secondary key to access the child is more proper 🙂

@cody1024d
Copy link
Author

cody1024d commented Nov 24, 2022

@AhmedLSayed9 v1.9.1 is working based on your solution above, thank you ahmed!

@AhmedLSayed9
Copy link
Owner

AhmedLSayed9 commented Nov 24, 2022

I'm unable to release the issue above. Can you provide a working sample that produce it?

@cody1024d
Copy link
Author

@AhmedLSayed9 This seems to be an issue on my end. I refactored by code, and it's no longer an issue. Sorry about that!. I'm editing my above comment so no one gets confused

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants