PyComponent#
Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).
import panel as pn
import param
pn.extension()
A PyComponent
, unlike a Viewer
class inherits the entire API of Panel components, including all layout and styling related parameters. It doesn’t just imitate a Panel component, it actually is one and therefore is a good option to build some composite widget made up of other widgets, a layout with some special behavior or a pane that renders some type of object in a way that is useful but does not require novel functionality.
from panel.custom import PyComponent
from panel.widgets import WidgetBase
class CounterButton(PyComponent, WidgetBase):
value = param.Integer(default=0)
def __panel__(self):
return pn.widgets.Button(
name=self._button_name, on_click=self._on_click
)
def _on_click(self, event):
self.value += 1
@param.depends("value")
def _button_name(self):
return f"count is {self.value}"
CounterButton()
Note
If you are looking to create new components using JavaScript, check out JSComponent
, ReactComponent
, or AnyWidgetComponent
instead.
API#
Attributes#
The PyComponent
class inherits the entire Panel Viewable
API including all sizing, layout and styling related parameters such as width
, height
, sizing_mode
etc.
Methods#
__panel__
: Must be implemented. Should return the Panel component or object to be displayed. Will be lazily evaluated and cached on render.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.
class StyledCounterButton(PyComponent):
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 _on_click(self, event):
self.value += 1
@param.depends("value")
def _button_name(self):
return f"Clicked {self.value} times"
def __panel__(self):
return pn.widgets.Button(
name=self._button_name,
on_click=self._on_click,
stylesheets=self._stylesheets
)
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:
from panel.custom import Child
class SingleChild(PyComponent):
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.
class SingleChild(PyComponent):
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:
from panel.custom import Children
class MultipleChildren(PyComponent):
objects = Children()
def __panel__(self):
return pn.Column(objects=self.param['objects'], styles={"background": "silver"})
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).