reflex-examples icon indicating copy to clipboard operation
reflex-examples copied to clipboard

Can you add an example of a dynamically updated dropdown list?

Open kazola opened this issue 2 years ago • 2 comments

Hi,

My pynecone-app is taking shape :) However, it is being a bit difficult for me to do things like in other options like Flask are a bit more straightforward.

For example, I would like to have 2 dropdowns or selects. The first one has the values '1' and '2'. The second one gets updated dynamically depending on the selection of the first one. If you select '1' in the first dropdown, the options in the second dropdown get updated to 'A, 'B'. If you select '2' in the first dropdown, the options in the second dropdown get updated to 'C', 'D'.

Can you post here a minimal example of this? I guess we should access the option list in the 2nd dropdown by accessing it referencing its ID but I cannot find an example of this.

Thanks a lot.

kazola avatar Dec 26 '22 09:12 kazola

Sure we can make an app that has this. I can post some code to show off this functionality

Alek99 avatar Dec 28 '22 07:12 Alek99

Hi @kazola , I'm not sure if this is still needed, but as a practice I was able to produce a minimum example that hopefully fits your need. Please see the following:

"""Welcome to Pynecone! This file create a counter app."""
import pynecone as pc
from typing import List

a_options = ["Option 1", "Option 2"]
options_b_1 = ["Option A", "Option B"]
options_b_2 = ["Option C", "Option D"]
b_options = []

class SelectState(pc.State):
    selected_option_a: str = "No selection yet."
    selected_option_b: str = "No selection yet."
    
    options_b : List[str] = []
    
    def set_selected_option_a(self, item):
        self.selected_option_a = item
        if item == "Option 1":
            self.options_b = options_b_1
        elif item == "Option 2":
            self.options_b = options_b_2
        else:
            self.options_b = []
        
    @pc.var
    def show_current_options_b(self):
        return f"Current bottom dropdown selections: {self.options_b}"
        


def index():
    """The main view."""
    return pc.center(
        pc.vstack(
            pc.select(
                a_options,
                placeholder="Select an example.",
                on_change=SelectState.set_selected_option_a,
            ),
            pc.heading(SelectState.show_current_options_b),
            pc.select(
                pc.foreach(SelectState.options_b, 
                    lambda opt_name: pc.option(
                        opt_name,
                        value=opt_name,
                    )),
                placeholder="Select an example.",
                on_change=SelectState.set_selected_option_b,
            ),
        ),
        padding_y="5em",
        font_size="2em",
        text_align="center",
    )


# Add state and page to the app.
app = pc.App(state=SelectState)
app.add_page(index, title="Dynamic Dropdown Example")
app.compile()
image
image
image

It seems that SelectState.options_b cannot be directly used as the options for the second dropdown, I guess this has something to do with how the default constructor works for each pc.option.

@Alek99 can you advise if this is the correct way to handle such use case? Also, to close this issue, should I also add some more examples/documentations into the component doc?

jay40233 avatar Apr 23 '23 15:04 jay40233