-
Hi, I'm trying to create closable tabs. In best case there should be an class MyLayout(SinglePageWithDrawerLayout):
def __init__(self, _server, template_name="main", show_drawer=True, width=300, **kwargs):
super().__init__(_server, template_name=template_name, show_drawer=show_drawer, width=width, **kwargs)
with self:
with self.drawer as drawer:
vuetify.VBtn("CLOSE_TAB", click=self.close_tab)
with self.content:
self.content_container = vuetify.VContainer(fluid=True,)
with self.content_container:
self.tabs = self.tabs = vuetify.VTabs(
v_model=("tab_idx", 0),
style="z-index: 1;",
color="grey",
change=(self.on_tab_change, "[$event]"),
)
self.tab_list = []
with self.tabs:
for tab_label in ["tab1", "tab2", "tab3"]:
self.tab_list.append(vuetify.VTab(tab_label))
def close_tab(self):
# What should be there? How to remove/close for example `tab1`? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 11 replies
-
You need to drive your tabs with a state variable and leveraging the |
Beta Was this translation helpful? Give feedback.
-
@jourdain thank you very much! The only thing is that: def on_add_tab_btn_clicked(self):
with self.state:
self.state.tab_names.append(f"tab{len(self.state.tab_names)}") doesn't update the tabs. The final code looks like follow: from trame.ui.vuetify2 import SinglePageLayout, SinglePageWithDrawerLayout
from trame.widgets import vuetify2 as vuetify
from trame.widgets import html, plotly, trame, client
from trame.app import get_server
class MyLayout(SinglePageWithDrawerLayout):
def __init__(self, _server, template_name="main", show_drawer=True, width=300, **kwargs):
super().__init__(_server, template_name=template_name, show_drawer=show_drawer, width=width, **kwargs)
# set the initial tab names
self.state.tab_names = ["tab0", "tab1", "tab2"]
with self:
with self.drawer as drawer:
self.add_btn()
with self.content:
self.content_container = vuetify.VContainer(fluid=True,)
with self.content_container:
self.tabs = self.tabs = vuetify.VTabs(
v_model=("tab_idx", 0),
style="z-index: 1;",
color="grey",
change=(self.on_tab_change, "[$event]"),
)
with self.tabs:
with vuetify.VTab("{{ name }}", v_for="name in tab_names", key="name"):
with vuetify.VBtn(icon=True, click=(self.on_close_tab_btn_clicked, "[name]")):
vuetify.VIcon("mdi-close")
def add_btn(self):
with self:
with self.drawer:
vuetify.VBtn("ADD_TAB", click=self.on_add_tab_btn_clicked)
def on_add_tab_btn_clicked(self):
self.state.tab_names.append(f"tab{len(self.state.tab_names)}")
self.state.dirty("tab_names")
def on_close_tab_btn_clicked(self, name):
print("name:", name)
self.state.tab_names.remove(name)
self.state.dirty("tab_names")
def on_tab_change(self, tab_idx):
print("on_tab_change:", tab_idx)
def main(server=None, **kwargs):
if server is None:
server = get_server(client_type="vue2")
MyLayout(server)
server.start()
if __name__ == "__main__":
main() closing_tabs.mp4 |
Beta Was this translation helpful? Give feedback.
-
Another way to write those methods def on_add_tab_btn_clicked(self):
self.state.tab_names = [*self.state.tab_names, f"tab{len(self.state.tab_names)}"]
def on_close_tab_btn_clicked(self, name):
self.state.tab_names = [t for t in self.state.tab_names if t != name] |
Beta Was this translation helpful? Give feedback.
-
@jourdain hi, After playing around with that example I've found that if I add for example a button to each tab then this will be a like a single button for all the tabs. So is there a way make these buttons independent on each tab? from trame.ui.vuetify2 import SinglePageLayout, SinglePageWithDrawerLayout
from trame.widgets import vuetify2 as vuetify
from trame.widgets import html, plotly, trame, client
from trame.app import get_server
class MyLayout(SinglePageWithDrawerLayout):
def __init__(self, _server, template_name="main", show_drawer=True, width=300, **kwargs):
super().__init__(_server, template_name=template_name, show_drawer=show_drawer, width=width, **kwargs)
# set the initial tab names
self.state.tab_names = ["tab0", "tab1", "tab2"]
with self:
with self.drawer as drawer:
self.add_btn()
with self.content:
self.content_container = vuetify.VContainer(fluid=True,)
with self.content_container:
self.tabs = self.tabs = vuetify.VTabs(
v_model=("tab_idx", 0),
style="z-index: 1;",
color="grey",
change=(self.on_tab_change, "[$event]"),
)
with self.tabs:
with vuetify.VTab("{{ name }}", v_for="name in tab_names", key="name"):
with vuetify.VBtn(icon=True, click=(self.on_close_tab_btn_clicked, "[name]")):
vuetify.VIcon("mdi-close")
with vuetify.VTabItem(v_for="name in tab_names", key="name"):
vuetify.VCheckbox(
v_model=("my_var", False),
on_icon="mdi-link",
off_icon="mdi-link-off",
classes="mx-1",
hide_details=True,
dense=True,
)
def add_btn(self):
with self:
with self.drawer:
vuetify.VBtn("ADD_TAB", click=self.on_add_tab_btn_clicked)
def on_add_tab_btn_clicked(self):
self.state.tab_names.append(f"tab{len(self.state.tab_names)}")
self.state.dirty("tab_names")
def on_close_tab_btn_clicked(self, name):
self.state.tab_names.remove(name)
self.state.dirty("tab_names")
def on_tab_change(self, tab_idx):
print("on_tab_change:", tab_idx)
def main(server=None, **kwargs):
if server is None:
server = get_server(client_type="vue2")
MyLayout(server)
server.start()
if __name__ == "__main__":
main() closing_tabs.mp4 |
Beta Was this translation helpful? Give feedback.
You need to drive your tabs with a state variable and leveraging the
v_for=
directive like in that example.