Viewer#
Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).
import panel as pn
pn.extension()
A Viewer
is a good abstraction for combining some business logic about your application with Panel components and then letting you use it as if it was a Panel component. It provides a useful abstraction extension of a simple Parameterized
class. Note however that it is not actually a Panel component, i.e. it does not behave like a widget, layout or pane. If you want to build a Panel component in Python the PyComponent
class is a better option.
import panel as pn
import param
from panel.viewable import Viewer
class CounterButton(Viewer):
value = param.Integer()
def __init__(self, **params):
super().__init__()
self._layout = pn.widgets.Button(
name=self._button_name, on_click=self._on_click, **params
)
def _on_click(self, event):
self.value += 1
@param.depends("value")
def _button_name(self):
return f"count is {self.value}"
def __panel__(self):
return self._layout
CounterButton()
Note
If you are looking to create new components using JavaScript, check out JSComponent
, ReactComponent
, or AnyWidgetComponent
instead.
API#
Attributes#
None. The Viewer
class does not have any special attributes. It is a simple param.Parameterized
class with a few additional methods. This also means you will have to add or support parameters like height
, width
, sizing_mode
, etc., yourself if needed.
Methods#
__panel__
: Must be implemented. Should return the Panel component or object to be displayed.servable
: This method serves the component using Panel’s built-in server when runningpanel serve ...
.show
: Displays the component in a new browser tab when runningpython ...
.
Usage#
Styling with CSS#
You can style the component by styling the component(s) returned by __panel__
using their styles
or stylesheets
attributes.
import panel as pn
import param
from panel.viewable import Viewer
class StyledCounterButton(Viewer):
value = param.Integer()
_stylesheets = [
"""
:host(.solid) .bk-btn.bk-btn-default
{
background: #0072B5;
color: white;
border: none;
padding: 10px;
border-radius: 4px;
}
:host(.solid) .bk-btn.bk-btn-default:hover {
background: #4099da;
}
"""
]
def __init__(self, **params):
super().__init__()
self._layout = pn.widgets.Button(
name=self._button_name,
on_click=self._on_click,
stylesheets=self._stylesheets,
**params,
)
def _on_click(self, event):
self.value += 1
@param.depends("value")
def _button_name(self):
return f"Clicked {self.value} times"
def __panel__(self):
return self._layout
StyledCounterButton().servable()
See the Apply CSS guide for more information on styling Panel components.
Displaying A Single Child#
You can display Panel components (Viewable
s) by defining a Child
parameter.
Let’s start with the simplest example:
import panel as pn
from panel.custom import Child
from panel.viewable import Viewer
class SingleChild(Viewer):
object = Child()
def __panel__(self):
return pn.Column("A Single Child", self.param.object.rx())
single_child = SingleChild(object=pn.pane.Markdown("A **Markdown** pane!"))
single_child.servable()
Calling self.param.object.rx()
creates a reactive expression which updates when the object
parameter is updated.
Let’s replace the object
with a Button
:
single_child.object = pn.widgets.Button(name="Click me")
Let’s change it back
single_child.object = pn.pane.Markdown("A **Markdown** pane!")
If you provide a non-Viewable
child it will automatically be converted to a Viewable
by pn.panel
:
SingleChild(object="A **Markdown** pane!").servable()
If you want to allow a certain type of Panel components only, you can specify the specific type in the class_
argument.
import panel as pn
from panel.custom import Child
from panel.viewable import Viewer
class SingleChild(Viewer):
object = Child(class_=pn.pane.Markdown)
def __panel__(self):
return pn.Column("A Single Child", self.param.object.rx())
SingleChild(object=pn.pane.Markdown("A **Markdown** pane!")).servable()
The class_
argument also supports a tuple of types:
object = Child(class_=(pn.pane.Markdown, pn.widgets.Button))
Displaying a List of Children#
You can also display a List
of Viewable
objects using the Children
parameter type:
import panel as pn
from panel.custom import Children
from panel.viewable import Viewer
class MultipleChildren(Viewer):
objects = Children()
def __init__(self, **params):
super().__init__(**params)
self._layout = pn.Column(objects=self.param['objects'], styles={"background": "silver"})
def __panel__(self):
return self._layout
MultipleChildren(
objects=[
pn.panel("A **Markdown** pane!"),
pn.widgets.Button(name="Click me!"),
{"text": "I'm shown as a JSON Pane"},
]
).servable()
You can change the item_type
to a specific subtype of Viewable
or a tuple of Viewable
subtypes.
References#
Tutorials#
How-To Guides#
Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).