Skip to content

Commit

Permalink
Showing 4 changed files with 215 additions and 0 deletions.
127 changes: 127 additions & 0 deletions examples/reference/panes/Placeholder.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"import panel as pn\n",
"\n",
"pn.extension()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `Placeholder` pane serves as a placeholder for other Panel components. It can be used to display a message while a computation is running, for example.\n",
"\n",
"#### Parameters:\n",
"\n",
"For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n",
"\n",
"* **`object`** (Any): The Panel object to display, if object is not already a Panel object it will be converted with the `panel(...)` function.\n",
"\n",
"___"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `Placeholder` pane can accept any Panel component as its argument, including other panes."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"placeholder = pn.pane.Placeholder(\"Hello\")\n",
"placeholder"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The benefit of using a `Placeholder` is that it allows you to replace the content of the pane without being restricted to a specific type of component. This means you can replace the placeholder with any other pane type, including plots, images, and widgets. You may either use the `update` method:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"placeholder.update(pn.widgets.TextInput(value=\"Hello again!\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"or set the `object` directly:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"placeholder.object = \"Hello once more!\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you'd like to temporarily replace the contents, you can use it as a context manager."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"placeholder = pn.pane.Placeholder(\"⏳ Idle\")\n",
"placeholder"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Upon execution of the cell below, the `Placeholder` pane will display `Starting...`, `Running...`, and `Complete!` in sequence, with a 1 second pause between each message, before finally displaying `Idle` again."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with placeholder:\n",
" placeholder.update(\"🚀 Starting...\")\n",
" await asyncio.sleep(1)\n",
" placeholder.update(\"🏃 Running...\")\n",
" await asyncio.sleep(1)\n",
" placeholder.update(\"✅ Complete!\")\n",
" await asyncio.sleep(1)"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
2 changes: 2 additions & 0 deletions panel/pane/__init__.py
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@
)
from .media import Audio, Video # noqa
from .perspective import Perspective # noqa
from .placeholder import Placeholder # noqa
from .plot import ( # noqa
YT, Bokeh, Matplotlib, RGGPlot,
)
@@ -84,6 +85,7 @@
"panel",
"PDF",
"Perspective",
"Placeholder",
"Plotly",
"PNG",
"ReactiveExpr",
58 changes: 58 additions & 0 deletions panel/pane/placeholder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
Defines the Placeholder pane which serves as a placeholder for other Panel components.
"""

from __future__ import annotations

import param

from ..pane.base import ReplacementPane


class Placeholder(ReplacementPane):
"""
The `Placeholder` pane serves as a placeholder for other Panel components.
It can be used to display a message while a computation is running, for
example.
Reference: https://panel.holoviz.org/reference/panes/Placeholder.html
:Example:
>>> with Placeholder("⏳ Idle"):
... placeholder.object = "🏃 Running..."
"""

def __init__(self, object=None, **params):
super().__init__(object=object, **params)
self._past_object = object # used to restore object when Placeholder is exited
self._temporary = False
if object is not None:
self._replace_panel()

@param.depends("object", watch=True)
def _replace_panel(self):
if not self._temporary:
self._past_object = self.object
self._update_inner(self.object)

def __enter__(self):
self._temporary = True
return self

def __exit__(self, exc_type, exc_value, traceback):
try:
self.object = self._past_object
finally:
self._temporary = False
return False

def update(self, object):
"""
Updates the object on the Placeholder.
Arguments
---------
object: The object to update the Placeholder with.
"""
self.object = object
28 changes: 28 additions & 0 deletions panel/tests/pane/test_placeholder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import param

from panel.pane.placeholder import Placeholder
from panel.widgets import IntInput


class TestPlaceholder:

def test_update_object(self):
placeholder = Placeholder("Idle")
placeholder.object = "Running..."
assert placeholder.object == "Running..."
placeholder.object = "New"
assert placeholder.object == "New"

def test_enter_exit(self):
placeholder = Placeholder("⏳ Idle")
with placeholder:
placeholder.object = "🏃 Running..."
assert placeholder.object == "🏃 Running..."
placeholder.object = "🚶 Walking..."
assert placeholder.object == "🚶 Walking..."
assert placeholder.object == "⏳ Idle"

def test_param_ref(self):
int_input = IntInput(name="IntInput", start=1, end=10, value=5)
placeholder = Placeholder(int_input.param.value)
assert isinstance(placeholder.object, param.Integer)

0 comments on commit dff4b5d

Please sign in to comment.