How to remove sidebar and update the webpage after template is served

Hi Everyone,

This is my first post in the community. I need to remove the sidebar from the template after the “Remove Sidebar” button is clicked. Below is a sample of my code, but the sidebar still appears on the webpage. Any help would be greatly appreciated!

import panel as pn
from panel.chat import ChatInterface

class ChatBot():
    def __init__(self, **params):
        super().__init__(**params)
        self.template = None
        self.chat_input = pn.widgets.TextInput(placeholder='Text here.')
        self.chat_interface = ChatInterface()
        self.chat_interface.callback = self.respond
        self.chat_interface.widgets = [self.chat_input]
        self.remove_button = pn.widgets.Button(name='Remove sidebar', button_type='primary')
        self.remove_button.on_click(self.remove_sidebar)
        self.sidebar_window = pn.Column(self.remove_button, width=300, align='center')

    def remove_sidebar(self, event):
        self.template.sidebar.remove(self.sidebar_window)

    async def respond(self, contents, user, chat_interface):
        yield {"value": f"Echo {contents}"}

    def app(self):
        self.template = pn.template.BootstrapTemplate(
            main=[self.chat_interface],
            sidebar=[self.sidebar_window]
        )
        return self.template

if __name__ == '__main__':
    pn.extension()
    pn.serve(lambda: ChatBot().app(), address='localhost')

Hi @Jason

Welcome to the community :+1:

The template .sidebar is not dynamic. I.e. you cannot remove elements after the app has loaded. It will be possible one day.

Instead you can use code like the below

import panel as pn

pn.extension()

button = pn.widgets.Button(name="Remove sidebar", button_type="primary")
button.js_on_click(
    code="""
document.getElementById('sidebar-button').style.display = 'none';
document.getElementById('sidebar').style.display = 'none';
"""
)

main = pn.pane.Markdown("# Click button to remove sidebar")


@pn.depends(button, watch=True)
def _update_main(_):
    main.object = "# Sidebar removed"


pn.template.FastListTemplate(sidebar=[button], main=[main]).servable()

Try it on PY.CAFE

2 Likes

Hi @Marc,

Thank you for the quick solution! Your code definitely works, but it’s slightly different from what I need.
I was wondering if it’s possible to run the JavaScript code to set display = 'none' within the Python function remove_sidebar(), which is called by remove_button.on_click().
The reason for this is that there is additional logic in the remove_sidebar() function, sidebar is conditionally removed based on the logic.

Ok. You can then create a custom JSComponent to toggle the sidebar

import panel as pn
import param

pn.extension()


class SidebarToggle(pn.custom.JSComponent):
    value = param.Boolean(doc="If True the sidebar is visible, if False it is hidden")

    _esm = """
export function render({ model }) {
    model.on('value', () => {
        if (model.value) {
            document.getElementById('sidebar-button').style.display = 'block';
            document.getElementById('sidebar').style.display = 'block';
        } else {
            document.getElementById('sidebar-button').style.display = 'none';
            document.getElementById('sidebar').style.display = 'none';    
        }
    });
}
"""


sidebar_toggle = SidebarToggle(value=True)

button = pn.widgets.Button(name="Remove sidebar", button_type="primary")
main = pn.pane.Markdown("# Click button to remove sidebar")


@pn.depends(button, watch=True)
def _update_main(_):
    sidebar_toggle.value = not sidebar_toggle.value

    if not sidebar_toggle.value:
        main.object = "# Click to add sidebar"
        button.name = "Add sidebar"
    else:
        button.name = "Remove sidebar"
        main.object = "# Click button to remove sidebar"


pn.template.FastListTemplate(sidebar=[sidebar_toggle], main=[pn.Column(button, main)]).servable()

Try on PY.CAFE

2 Likes

Hi Marc,

Appreciate your the quick responding. Will give it a try.

1 Like

Hi Marc,
Run your code successfully under PY.CAFE environment but fail on my computer with panel==1.4.5 module installed. The error is module ‘panel’ has no attribute ‘custom’.

Follow up:
Upgrade to panel 1.5.1 and doesn’t get this error.
Works great and it’s exactly what I need. Marked it as solution.
Thank you so much Marc!!

2 Likes

Related Github issue: