posit-dev / py-shiny

Shiny for Python
https://shiny.posit.co/py/
MIT License
1.32k stars 81 forks source link

Keep order of selection if multiple items were selected in `input_selectize` #1751

Open DvGils opened 3 weeks ago

DvGils commented 3 weeks ago

Hi!

I noticed Shiny will not keep the order of items that you set in the selected argument. For my use case this ordering matters. The following code will set the order to "A", "C", "D" instead of "C", "A", "D"

from shiny import App, ui, render, reactive

app_ui = ui.page_fluid(
    ui.h3("Order of Selected Items in ui.input_selectize()"),
    ui.input_selectize(
        "my_selectize",
        "Choose items:",
        choices=["A", "B", "C", "D"],
        selected=["C", "A", "D"],
        multiple=True,
    ),
)

def server(input, output, session): ...

app = App(app_ui, server)

Pretty sure the issue lies in:

#_input_selectize.py
def _render_choices(
    x: _SelectChoices, selected: Optional[str | list[str]] = None
) -> TagList:
    result = TagList()

    if x is None:
        return result

    for k, v in x.items():
        if isinstance(v, Mapping):
            result.append(
                tags.optgroup(
                    *(_render_choices(cast(_SelectChoices, v), selected)), label=k
                )
            )
        else:
            is_selected = False
            if isinstance(selected, list):
                is_selected = k in selected
            else:
                is_selected = k == selected

            result.append(tags.option(v, value=k, selected=is_selected))

    return result

Is there a chance this can be fixed?

An additional note; it is strange to me that input.my_selectize() will return a tuple, but the selected will not accept a tuple, only a list.