Textualize/textual

Select constructor shouldn't send Changed message

willmcgugan opened this issue · 1 comments

Discussed in #4368

Originally posted by villekr March 31, 2024
After change in #3869 all widgets send 'Changed' events even during the initialization. What is the correct way to ignore these 'Changed' events during the initialization? @rodrigogiraoserrao

Let's say I have the following situation where 'secondary' Select-widget's selection depends on the selected value of 'primary' Select-widget. Initially both have some values.

Expected:

  • primary = "drink"
  • secondary = "juice"

Actual:

  • primary = "drink"
  • secondary = "water"
from textual import on
from textual.app import App, ComposeResult
from textual.widgets import Header, Select

ITEMS = {"food": ["pizza", "burger", "salad"], "drink": ["water", "soda", "juice"]}


class SelectApp(App):
    CSS_PATH = "select.tcss"
    primary = "drink"
    secondary = "juice"

    def compose(self) -> ComposeResult:
        primary_items = [(item, item) for item in ITEMS]
        secondary_items = [(item, item) for item in ITEMS[self.primary]]
        yield Header()
        yield Select(
            primary_items,
            value=self.primary,
            prompt="Select Category",
            id="primary",
            classes="settings_option",
            allow_blank=False,
        )
        yield Select(
            secondary_items,
            value=self.secondary,
            prompt="Select Item",
            id="secondary",
            classes="settings_option",
            allow_blank=False,
        )
        self.title = f"{self.primary=} {self.secondary=}"

    @on(Select.Changed)
    def select_changed(self, event: Select.Changed) -> None:
        if event.control.id == "primary":
            self.primary = event.value
            items = ITEMS[event.value]
            widget: Select = self.query_one("#secondary")
            widget.set_options((item, item) for item in items)
        if event.control.id == "secondary":
            self.secondary = event.value
        self.title = f"{self.primary=} {self.secondary=}"


if __name__ == "__main__":
    app = SelectApp()
    app.run()

```</div>

Don't forget to star the repository!

Follow @textualizeio for Textual updates.