ModalScreen only loading once #5490
-
Hello, I'm having a issue where a ModalScreen only loads once unless I restart my app. I have a MainScreen containing a Datatable and a binding to push a Screen to edit a particular row. When the EditScreen mounts, it first pushes the EditConfirmationScreen to allow the user to submit the ID of the row they want to edit, which is returned to the EditScreen. The EditConfirmationScreen only loads the first time the EditScreen is mounted, so I'm unable to edit anything further without restarting the app. I'd like to be able to do multiple edits without restarting. Thanks! from textual.app import App, ComposeResult
from textual import on, work
from textual.screen import ModalScreen, Screen
from textual.widgets import Button, DataTable, Footer, Header, Input, RichLog, Static
class EditConfirmationScreen(ModalScreen[str | None]):
"""Modal screen to confirm ID of book to be edited"""
BINDINGS = [("escape", "app.pop_screen", "Cancel")]
def compose(self) -> ComposeResult:
yield Input(placeholder="ID", id="id-edit")
yield Button("Edit", id="edit-submit")
@on(Button.Pressed, "#edit-submit")
def edit_book_pressed(self) -> None:
book_id = self.query_one("#id-edit")
if book_id:
self.dismiss(book_id.value)
else:
self.dismiss(None)
class EditScreen(Screen):
"""Modal Screen to provide inputs to edit an existing book"""
BINDINGS = [("escape", "app.pop_screen", "Cancel")]
def compose(self) -> ComposeResult:
yield Input(placeholder="Column1", id="column1")
yield Input(placeholder="Column2", id="column2")
yield Button("Submit", id="edit-submit")
yield Footer()
@work
async def on_mount(self) -> None:
book_id = await self.app.push_screen_wait(EditConfirmationScreen())
if book_id:
self.book_id = book_id
else:
self.app.push_screen("books")
@on(Button.Pressed, "#edit-submit")
def edit_submit_pressed(self):
self.app.push_screen("books")
class MainScreen(Screen):
"""Widget to manage book collection."""
BINDINGS = [
("e", "app.push_screen('edit')", "Edit"),
]
def compose(self) -> ComposeResult:
yield Header()
yield DataTable(id="table")
yield Footer()
def on_mount(self) -> None:
self.load_data()
def _on_screen_resume(self) -> None:
self.load_data()
def load_data(self) -> None:
table = self.query_one("#table")
table.clear(columns=True)
columns = ["column1", "column2"]
values = [("value1", "value2"), ("val1", "val2")]
table.add_columns(*columns)
table.add_rows(values)
class Tracker(App):
SCREENS = {
"books": MainScreen,
"edit": EditScreen,
"edit_confirmation": EditConfirmationScreen,
}
BINDINGS = [
("b", "push_screen('books')", "Books"),
]
def compose(self) -> ComposeResult:
yield Header()
yield Footer()
def on_mount(self) -> None:
self.theme = "gruvbox"
self.push_screen(MainScreen())
if __name__ == "__main__":
app = Tracker()
app.run() |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Screens defined in If I've understood correctly, the problem is that your screen is actually only mounted once, as it will still exist on the screen stack. |
Beta Was this translation helpful? Give feedback.
Screens defined in
SCREENS
are installed screens that exist for the lifetime of your app. Are you sure that's what you want in your case?If I've understood correctly, the problem is that your screen is actually only mounted once, as it will still exist on the screen stack.