tab not showen by default when i am clearing TabbedContent with new tabs #3238
-
I have two sections in my program (Tabbed Content) and (Filtering Section) the Filtering Section should do as follow when filter item is checked it should change all items in Tabbed Content with new one here is the problem come when i check the filtering items everything go ok and the tabbed content get the new data but no content appear in the tab content directly then i should click on the tab name to show the content tab as explained in video my code as follow class AdminApp(App): # Adding or removing item to this array give the accessibility to mentioned role to use this class _ALLOWED_ACCESS_ROLES = ["admin"] CSS_PATH = "style.css" # If the filter mode is True then requests of selected filtering admin will be retrieved is_filter_mode_on = False def __init__(self, current_logged_user): super().__init__() self.current_logged_user = current_logged_user # Will holds all the users that will be used to filter by self.filtering_by_users = [] def compose(self) -> ComposeResult: yield Header() yield Footer() yield Horizontal( StatesTabCreator(self), SearchCreator(), FiltersCreator(self) ) the class that handle checkbox click: class FilterItem(Static): def __init__(self, user, root_app): super().__init__() self.user: UserModel = user self.root_app: AdminApp = root_app def compose(self) -> ComposeResult: yield Checkbox(classes=f"filter-checkbox-user") yield Label(f"[b]{self.user.get_username()}[/]", id=f"filter-username-user{self.user.get_id()}") @on(Checkbox.Changed, ".filter-checkbox-user") def filter_checkbox_clicked(self, event: Checkbox.Changed): selected_username = self.user.get_username() is_checkbox_checked = event.checkbox.value if is_checkbox_checked: self.root_app.filtering_by_users.append(selected_username) else: if selected_username in self.root_app.filtering_by_users: self.root_app.filtering_by_users.remove(selected_username) state_tab_creator: StatesTabCreator = self.root_app.query_one(StatesTabCreator) self.root_app.is_filter_mode_on = True state_tab_creator.unmount_elements() state_tab_creator.compose_filtering_users_requests() tabbed_content: TabbedContent = self.root_app.query_one(TabbedContent) def enable_filter_mode(self): if len(self.root_app.filtering_by_users) == 0: self.root_app.is_filter_mode_on = False else: self.root_app.is_filter_mode_on = True the class that handle recreation of tabbed content tab: class StatesTabCreator(Widget): current_selected_tab_id = Reactive("") def __init__(self, root_app): super().__init__() self.state_dao = connection_dao self.current_state = "" self.root_app: AdminApp = root_app def compose(self) -> ComposeResult: states = self.state_dao.get_states() with TabbedContent(): for index, state in enumerate(states): self.current_state = state yield CustomTabPane(state, state.get_state(), self.root_app) @on(TabbedContent.TabActivated) def state_tab_selected(self, event: TabbedContent.TabActivated): self.current_selected_tab_id = event.tab.id state_tab_content_query_parameter = f"VerticalScroll#vertical-container-{self.current_selected_tab_id}" # Responsible for to check if there is any requested that its state are changed ,its new state equal to the # current tab state if yes it will be mounted here to be displayed on the current tab for index, item in enumerate(cached_state_items): item_state_id_query = f"state{item.state.get_id()}" if item_state_id_query == self.current_selected_tab_id: self.query_one(state_tab_content_query_parameter).mount(item) cached_state_items.remove(item) def unmount_elements(self): tabbed_content: TabbedContent = self.query_one(TabbedContent) tabbed_content.clear_panes() def compose_filtering_users_requests(self): states = self.state_dao.get_states() tabbed_content: TabbedContent = self.query_one(TabbedContent) for index, state in enumerate(states): tabbed_content.add_pane(CustomTabPane(state=state, title=state.get_state(), root_app=self.root_app)) i also tried active to solve the problem but the screen is showing content and disappear immediately self.query_one(TabbedContent).active = self.current_selected_tab_id |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
There's quite a lot of code here which is difficult to debug as it isn't self-contained( i.e. it can't just be copied, pasted and run). I've created a quick minimal reproducible example below - I'd recommend trying to do this where possible as it greatly improve the chances of getting a quick fix. This was hacked together so perhaps I'm missing something, but I'm seeing the same issue where the updates only seem to display after switching tabs. from textual import on
from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.widgets import Label, SelectionList, TabbedContent, TabPane
USERS = {"MohamedElgamal", "TomJGooding", "davep"}
class AdminApp(App):
CSS = """
TabbedContent {
width: 70%
}
SelectionList {
width: 30%;
height: 100%;
padding: 1;
border: panel $primary;
}
Label {
height: 3;
width: 100%;
border: round $success;
}
"""
def compose(self) -> ComposeResult:
with Horizontal():
yield TabbedContent()
yield SelectionList[str]()
def on_mount(self) -> None:
user_selection = self.query_one(SelectionList)
user_selection.border_title = "Filter Users"
for user in USERS:
user_selection.add_option((user, user))
self.update_tabbed_content([])
def update_tabbed_content(self, users_filter: list[str]) -> None:
users: set[str]
if not users_filter:
users = USERS
else:
users = {user for user in USERS if user in users_filter}
tabbed_content = self.query_one(TabbedContent)
tabbed_content.clear_panes()
for tab_title in ("submitted", "in progress", "completed"):
tab_pane = TabPane(tab_title, *(Label(user) for user in users))
tabbed_content.add_pane(tab_pane)
@on(SelectionList.SelectedChanged)
def on_users_selected_changed(self) -> None:
user_selection = self.query_one(SelectionList)
self.update_tabbed_content(user_selection.selected)
if __name__ == "__main__":
app = AdminApp()
app.run() |
Beta Was this translation helpful? Give feedback.
-
Thanks for the clear example of the issue here @TomJGooding. I think the core issue here is the clearing of the content followed right away by the adding of new panes. Given that both With these changes to your code it seems to work as I think it's supposed to be working (I'll admit I'm a little unclear as to exactly what it's supposed to be doing): --- tom_mre_orig.py 2023-09-05 20:00:38
+++ tom_mre.py 2023-09-05 19:58:34
@@ -31,15 +31,15 @@
yield TabbedContent()
yield SelectionList[str]()
- def on_mount(self) -> None:
+ async def on_mount(self) -> None:
user_selection = self.query_one(SelectionList)
user_selection.border_title = "Filter Users"
for user in USERS:
user_selection.add_option((user, user))
- self.update_tabbed_content([])
+ await self.update_tabbed_content([])
- def update_tabbed_content(self, users_filter: list[str]) -> None:
+ async def update_tabbed_content(self, users_filter: list[str]) -> None:
users: set[str]
if not users_filter:
users = USERS
@@ -47,15 +47,15 @@
users = {user for user in USERS if user in users_filter}
tabbed_content = self.query_one(TabbedContent)
- tabbed_content.clear_panes()
+ await tabbed_content.clear_panes()
for tab_title in ("submitted", "in progress", "completed"):
tab_pane = TabPane(tab_title, *(Label(user) for user in users))
- tabbed_content.add_pane(tab_pane)
+ await tabbed_content.add_pane(tab_pane)
@on(SelectionList.SelectedChanged)
- def on_users_selected_changed(self) -> None:
+ async def on_users_selected_changed(self) -> None:
user_selection = self.query_one(SelectionList)
- self.update_tabbed_content(user_selection.selected)
+ await self.update_tabbed_content(user_selection.selected)
if __name__ == "__main__": In conclusion: I think you want to be awaiting the clear of the panes before going ahead and adding more. Another approach could, I think, be to clear the content then do the adding of the new panes inside an event handler that catches the |
Beta Was this translation helpful? Give feedback.
Thanks for the clear example of the issue here @TomJGooding. I think the core issue here is the clearing of the content followed right away by the adding of new panes. Given that both
clear_panes
andadd_pane
are awaitable things are getting rather confused.With these changes to your code it seems to work as I think it's supposed to be working (I'll admit I'm a little unclear as to exactly what it's supposed to be doing):