I need to use a modal in my app.
Is there any existing solution?
if not, can you guide me on using HTML pane to do it?
Hi @ItamarShDev
How to solve this depends on what you want to do with the model.
Should it contain
- Text
- Markdown
- Html
- Panel Buttons
- Panel layouts, panes or widgets?
I believe you would have to do one of the following.
- Mess with
pn.pane.HTML
using how to css modals or similar. - Create a custom panel template using how to css modals or similar.
- Implement a custom Bokeh Extension.
- Wait for the new templates in Panel 0.10. I believe they support modals. But I am not sure.
- Wait for a modal to be added to the awesome-panel-extensions package. I have it on the radar but has not done it yet.
- For example I hope to add the MWC dialog one day.
I would try the first or second option depending on your use case.
And please add a Feature Request to Panel on Github describing your use case. That will help.
Hi @ItamarShDev
Did you find a solution? And which?
I think I will be experimenting a bit with this today as I need to learn about it too.
Regarding whether it’s in Panel 0.10 I’m not sure. I can see that there is a statement in that direction https://github.com/holoviz/panel/pull/1421#issuecomment-653582948 though.
Hi @ItamarShDev.
I’ve created an example based on a custom Panel Template.
Check it out live at https://awesome-panel.org/dialog_template
You can find the most recent code here https://github.com/MarcSkovMadsen/awesome-panel/tree/master/application/pages/dialog_template.
I include the current code below for completeness
template.html
{% extends base %}
{% block postamble %}
<!-- https://shoelace.style/ -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.19/dist/shoelace/shoelace.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.19/dist/shoelace/shoelace.esm.js"></script>
<style>
body, .bk-root .bk, .bk-root .bk:before, .bk-root .bk:after {
font-family: var(--sl-input-font-family);
}
</style>
{% endblock %}
<!-- goes in body -->
{% block contents %}
{{ embed(roots.header) }}
<div id="main" style="margin: 25px">
{{ embed(roots.main) }}
<br/>
<!-- https://shoelace.style/components/dialog -->
<sl-dialog label="{{ dialog_label }}" class="dialog-overview" style="--width: 550px;--height: 500px;">
{{ embed(roots.dialog) }}
<sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>
<sl-button>Open Dialog</sl-button>
</div>
<script>
(() => {
const dialog = document.querySelector('.dialog-overview');
const openButton = dialog.nextElementSibling;
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
openButton.addEventListener('click', () => dialog.show());
closeButton.addEventListener('click', () => dialog.hide());
})();
</script>
{% endblock %}
template.py
"""Custom Panel Template With a Dialog"""
import pathlib
import panel as pn
import param
TEMPLATE = (pathlib.Path(__file__).parent / "template.html").read_text()
class TemplateWithDialog(pn.template.Template):
"""Custom Panel Template With a Dialog"""
dialog_open = param.Action()
dialog_close = param.Action()
TEMPLATE = (pathlib.Path(__file__).parent / "template.html").read_text()
def __init__(self, header, main, dialog, dialog_label: str):
super().__init__(
template=TEMPLATE,
)
self.add_panel("header", header)
self.add_panel("main", main)
self.add_panel("dialog", dialog)
self.add_variable("dialog_label", dialog_label)
app.py
"""Panel application show casing a Custom Panel Template With a Dialog"""
import hvplot.pandas # pylint: disable=unused-import
import panel as pn
from bokeh.sampledata import sea_surface_temperature as sst
from .template import TemplateWithDialog
def _get_sea_surface_temperature_plot():
if "dialog_template_plot" not in pn.state.cache:
pn.state.cache["dialog_template_plot"] = sst.sea_surface_temperature.hvplot.kde().opts(
height=300, width=500
)
return pn.state.cache["dialog_template_plot"]
def view():
"""Returns a Panel application show casing a Custom Panel Template With a Dialog"""
top_panel = pn.Row(
pn.pane.PNG(
"https://panel.holoviz.org/_static/logo_horizontal.png",
height=50,
margin=10,
link_url="https://panel.holoviz.org",
sizing_mode="stretch_width",
),
background="black",
sizing_mode="stretch_width",
)
main_panel = pn.Column(
"This is a Panel application with a dialog",
"Provided by awesome-panel.org",
sizing_mode="stretch_width",
)
dialog_panel = pn.Column(_get_sea_surface_temperature_plot(), sizing_mode="fixed")
template = TemplateWithDialog(
header=top_panel,
main=main_panel,
dialog=dialog_panel,
dialog_label="HvPlot - Sea surface temperature kde",
)
return template
Very nice example! I’ve been wondering how to do that.
We should learn more about custom templates @Jhsmit
With a component library like shoelace, fast, material Mwc, sap ui 5 etc you can actually create lots of awesome and modern layouts for you panel app.
Amazing! can we communicate with that example?
For example, get yes/no answer, get inputs values and such?
Yes.
You can place any panel components inside the pn.Column of the dialog_panel. So replace the plot with markdown, checkboxes, radioboxes etc.
[quote=“Marc, post:4, topic:1207”]
Hello Guys,
Do these do anything? Can we get feedback from shoelace when the ‘close’ button is pressed?
dialog_open = param.Action()
dialog_close = param.Action()
Thanks.
I would think so. But how i actually dont know.