Skip to content
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Bug fixes

* Fixed numerous issues related to programmatically updating selectize options. (#2053)
* `update_selectize(options=...)` no longer gets ignored when `server=False` (the default).
* `update_selectize(options=...)` now works as expected in a module.

* Fixed an issue with `update_selectize()` to properly display labels with HTML reserved characters like "&" (#1330)

* Fixed an issue with `ui.Chat()` sometimes wanting to scroll a parent element. (#1996)
Expand Down
20 changes: 9 additions & 11 deletions shiny/ui/_input_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,22 +722,20 @@ def update_selectize(

session = require_active_session(session)

if options is not None:
cfg = tags.script(
json.dumps(options),
type="application/json",
data_for=resolve_id(id),
data_eval=json.dumps(extract_js_keys(options)),
)
session.send_input_message(id, {"config": cfg.get_html_string()})

if not server:
return update_select(
id, label=label, choices=choices, selected=selected, session=session
)

if options is not None:
cfg = TagList(
tags.script(
json.dumps(options),
type="application/json",
data_for=id,
data_eval=json.dumps(extract_js_keys(options)),
)
)
session.send_input_message(id, drop_none({"config": cfg.get_html_string()}))

# Transform choices to a list of dicts (this is the form the client wants)
# [{"label": "Foo", "value": "foo", "optgroup": "foo"}, ...]
flat_choices: list[FlatSelectChoice] = []
Expand Down
34 changes: 34 additions & 0 deletions tests/playwright/shiny/components/selectize/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from shiny import App, Inputs, Outputs, Session, module, reactive, ui


@module.ui
def reprex_selectize_ui(label: str):
return ui.input_selectize("x", label, choices=[], multiple=True)


@module.server
def reprex_selectize_server(
input: Inputs, output: Outputs, session: Session, server: bool = True
):
@reactive.effect
def _():
ui.update_selectize(
"x",
choices=[f"Foo {i}" for i in range(3)],
server=server,
options={"placeholder": "Search"},
)


app_ui = ui.page_fluid(
reprex_selectize_ui("serverside", "Server"),
reprex_selectize_ui("clientside", "Client"),
)


def server(input: Inputs, output: Outputs, session: Session):
reprex_selectize_server("serverside", server=True)
reprex_selectize_server("clientside", server=False)


app = App(app_ui, server, debug=True)
23 changes: 23 additions & 0 deletions tests/playwright/shiny/components/selectize/test_selectize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# import pytest
from playwright.sync_api import Page, expect

from shiny.playwright import controller
from shiny.run import ShinyAppProc


def test_selectize(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

expect(page.get_by_placeholder("Search")).to_have_count(2)

selectize_menu = controller.InputSelectize(page, "serverside-x")
selectize_menu.expect_choices(["Foo 0", "Foo 1", "Foo 2"])
selectize_menu.expect_multiple(True)
selectize_menu.set(["Foo 0", "Foo 1"])
selectize_menu.expect_selected(["Foo 0", "Foo 1"])

selectize_menu2 = controller.InputSelectize(page, "clientside-x")
selectize_menu2.expect_choices(["Foo 0", "Foo 1", "Foo 2"])
selectize_menu2.expect_multiple(True)
selectize_menu2.set(["Foo 0", "Foo 1"])
selectize_menu2.expect_selected(["Foo 0", "Foo 1"])
Loading