From 2798e35bf30925386e3d0c67b6e67237f30b017e Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:20:08 -0700 Subject: [PATCH 1/3] update best practices --- doc/how_to/best_practices/dev_experience.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/how_to/best_practices/dev_experience.md b/doc/how_to/best_practices/dev_experience.md index a17d667f75..6520ba3d4a 100644 --- a/doc/how_to/best_practices/dev_experience.md +++ b/doc/how_to/best_practices/dev_experience.md @@ -46,11 +46,13 @@ clicks = pn.bind(show_clicks, button.clicks) # not button.clicks! pn.Row(button, clicks) ``` -## Inherit from `pn.viewer.Viewer` +## Inherit from `pn.viewer.Viewer` or `pn.custom.PyComponent` ### Good -`param.Parameterized` is a very general class that can be used separately from Panel for working with Parameters. But if you want a Parameterized class to use with Panel, it is usually appropriate to inherit from the Panel-specific class `pn.viewable.Viewer` instead, because `Viewer` allows direct invocation of the class, resembling a native Panel object. +`param.Parameterized` is a very general class that can be used separately from Panel for working with Parameters. + +But if you want a Parameterized class to use with Panel, it is usually appropriate to inherit from the Panel-specific class `pn.viewable.Viewer` instead, because `Viewer` allows direct instantiation of the `Viewer` class, resembling a native Panel object. For example, it's possible to use `ExampleApp().servable()` instead of `ExampleApp().view().servable()`. @@ -68,6 +70,17 @@ class ExampleApp(pn.viewable.Viewer): ExampleApp().servable(); ``` +`Viewer` is ideal if you're building a class with some fairly specific business logic, *but* if you are simply building a reusable component assembled from other Panel components use [`PyComponent`](https://panel.holoviz.org/reference/custom_components/PyComponent.html) instead. + +```python +class MultipleChildren(PyComponent): + + objects = Children() + + def __panel__(self): + return pn.Column(objects=self.param['objects'], styles={"background": "silver"}) +``` + ### Okay Inheriting from `param.Parameterized` also works, but should be reserved for cases where there's no Panel output. From fbe6327433f287f3209bde7b12d64df2f6a3ab0d Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:27:28 -0700 Subject: [PATCH 2/3] Update user_experience.md --- doc/how_to/best_practices/user_experience.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/how_to/best_practices/user_experience.md b/doc/how_to/best_practices/user_experience.md index 7cb035e752..1023aa0aff 100644 --- a/doc/how_to/best_practices/user_experience.md +++ b/doc/how_to/best_practices/user_experience.md @@ -150,6 +150,19 @@ pn.state.onload(onload) ### Good +Set `loading=pn.state.param.busy` to overlay a spinner while processing to let the user know it's working. + +```{pyodide} +def process_load(event): + time.sleep(3) + +button = pn.widgets.Button(name="Click me", on_click=process_load) +widget_box = pn.WidgetBox(button, loading=pn.state.param.busy, height=300, width=300) +widget_box +``` + +### Good + Set `loading=True` to show a spinner while processing to let the user know it's working. ```{pyodide} @@ -193,8 +206,6 @@ Use: - `finally` block to update values regardless ```{pyodide} -import time - def compute(divisor): try: busy.value = True From 587ed90edc9bd075be1d841fab9c6206a3967389 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 20 Sep 2024 15:58:57 +0200 Subject: [PATCH 3/3] Apply suggestions from code review --- doc/how_to/best_practices/dev_experience.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/how_to/best_practices/dev_experience.md b/doc/how_to/best_practices/dev_experience.md index 6520ba3d4a..5a20cdcf8b 100644 --- a/doc/how_to/best_practices/dev_experience.md +++ b/doc/how_to/best_practices/dev_experience.md @@ -70,7 +70,7 @@ class ExampleApp(pn.viewable.Viewer): ExampleApp().servable(); ``` -`Viewer` is ideal if you're building a class with some fairly specific business logic, *but* if you are simply building a reusable component assembled from other Panel components use [`PyComponent`](https://panel.holoviz.org/reference/custom_components/PyComponent.html) instead. +`Viewer` is ideal if you're building a class with some fairly specific business logic, *but* if you are building a reusable component assembled from other Panel components use [`PyComponent`](https://panel.holoviz.org/reference/custom_components/PyComponent.html) instead. ```python class MultipleChildren(PyComponent):