Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize API guides #4759

Merged
merged 4 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions doc/explanation/api/api_context.md

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ plot_fns = {
This example demonstrates how APIs in Panel differ, to see the same app implemented using a different API visit:

- [Declarative API](stocks_declarative)
- [Interact API](stocks_interact)
- [Reactive API](stocks_reactive)

Other APIs in Panel are all reactive in some way, triggering actions whenever manipulating a widget causes a parameter to change, without users writing code to trigger callbacks explicitly. The callback based API on the other allows complete low-level control of precisely how the different components of the app are updated, but they can quickly become unmaintainable because the complexity increases dramatically as more callbacks are added. The approach works by defining callbacks using the ``.param.watch`` API that either update or replace the already rendered components when a watched parameter changes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ plot_fns = {
This example demonstrates how APIs in Panel differ, to see the same app implemented using a different API visit:

- [Callback API](stocks_callbacks)
- [Interact API](stocks_interact)
- [Reactive API](stocks_reactive)

The declarative API expresses the app entirely as a single ``Parameterized`` class with parameters to declare the inputs, rather than explicit widgets. The parameters are independent of any GUI code, which can be important for maintaining large codebases, with parameters and functionality defined separately from any GUI or panel code. Once again the ``depends`` decorator is used to express the dependencies, but in this case the dependencies are expressed as strings referencing class parameters, not parameters of widgets. The parameters and the ``plot`` method can then be laid out independently, with Panel used only for this very last step.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ This example demonstrates how APIs in Panel differ, to see the same app implemen

- [Callback API](stocks_callbacks)
- [Declarative API](stocks_declarative)
- [Interact API](stocks_interact)

The reactive programming model is similar to the ``interact`` function but relies on the user (a) explicitly instantiating widgets, (b) declaring how those widgets relate to the function arguments (using the ``bind`` function), and (c) laying out the widgets and other components explicitly. In principle we could reuse the ``get_plot`` function from above here but for clarity we will repeat it:
The reactive programming model relies on the user (a) explicitly instantiating widgets, (b) declaring how those widgets relate to the function arguments (using the ``bind`` function), and (c) laying out the widgets and other components explicitly. In principle we could reuse the ``get_plot`` function from above here but for clarity we will repeat it:

```{pyodide}
backend = pn.widgets.Select(name='Backend', options=plot_fns)
Expand Down
80 changes: 80 additions & 0 deletions doc/explanation/api/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# APIs

Panel can be used to make a simple app in minutes, but you can also create complex apps with fully customized behavior and appearance or even flexibly integrate GUI support into long-term, large-scale software projects.

To accommodate these different ways of using Panel, multiple APIs are available. Nearly all of the functionality of Panel can be accessed using any of the APIs, but each makes certain things much easier than others.

Let's go work through each API with an example app while pointing out the benefits and drawback along the way. Here's a quick summary:
1. The ``Reactive API`` approach allows you to define a reactive function that is bound directly to a set of widgets using `pn.bind`. This API is efficient while still being explicit, flexible, and maintainable. We recommend this for most users, especially those that are new to Panel.
2. When writing libraries or other code that might be used independently of the actual GUI, a Parameterized class can be a great way to organize the code. In this case, dive into the ``Declarative API``.
3. If you need low-level control or want to complement any of the other approaches, defining explicit callbacks can be done with the ``Callbacks API``.

::::{grid} 1 2 2 3
:gutter: 1 1 1 2

:::{grid-item-card} {octicon}`infinity;2.5em;sd-mr-1 sd-animate-grow50` 1. Reactive API
:link: reactive
:link-type: doc

Linking functions or methods to widgets using ``pn.bind`` or the equivalent ``pn.depends`` decorator.
:::

:::{grid-item-card} {octicon}`codespaces;2.5em;sd-mr-1 sd-animate-grow50` 2. Declarative API
:link: parameterized
:link-type: doc

Declare parameters and their ranges in `Parameterized` classes, then get GUIs (and value checking!) for free.
:::

:::{grid-item-card} {octicon}`link;2.5em;sd-mr-1 sd-animate-grow50` 3. Callbacks API
:link: callbacks
:link-type: doc

Generate a UI by manually declaring callbacks that update panels or panes.
:::

::::

## Examples

Below are additional recipes using each API to create slightly more advanced apps.

::::{grid} 1 2 2 3
:gutter: 1 1 1 2

:::{grid-item-card} Stock Explorer - Callback API
:img-top: https://assets.holoviz.org/panel/how_to/apis/stocks_callback.png
:link: examples/stocks_callbacks
:link-type: doc

Build a stock explorer app using the `.param.watch` callback API.
:::

:::{grid-item-card} Stock Explorer - Declarative API
:img-top: https://assets.holoviz.org/panel/how_to/apis/stocks_declarative.png
:link: examples/stocks_declarative
:link-type: doc

Build a stock explorer app using the Param based declarative API.
:::

:::{grid-item-card} Stock Explorer - Reactive API
:img-top: https://assets.holoviz.org/panel/how_to/apis/stocks_reactive.png
:link: examples/stocks_reactive
:link-type: doc

Build a stock explorer app using the reactive API.
:::

::::

```{toctree}
:titlesonly:
:hidden:
:maxdepth: 2

reactive
interact
parameterized
callbacks
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Parameterized Classes
# Declarative API

The [Param](http://param.holoviz.org) library allows expressing the parameters of a class (or a hierarchy of classes) completely independently of a GUI implementation. Panel and other libraries can then take those parameter declarations and turn them into a GUI to control the parameters. This approach allows the parameters controlling some computation to be captured specifically and explicitly (but as abstract parameters, not as widgets). Then thanks to the `@param.depends` decorator (similar to `@panel.depends` but for use in Parameterized classes without any dependency on Panel), it is then possible to directly express the dependencies between the parameters and the computation defined in some method on the class, all without ever importing Panel or any other GUI library. The resulting objects can then be used in both GUI and non-GUI contexts (batch computations, scripts, servers).

Expand Down
16 changes: 8 additions & 8 deletions doc/how_to/apis/reactive.md → doc/explanation/api/reactive.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Reactive functions
# Reactive API

The `pn.bind` reactive programming API is very similar to the [`interact` function](interact) but is more explicit about widget selection and layout. `pn.bind` requires the programmer to select and configure widgets explicitly and to lay out components explicitly, without relying on inference of widget types and ranges and without any default layouts. Specifying those aspects explicitly provides more power and control, but does typically take a bit more code and more knowledge of widget and layout components than using `interact` does. Once widgets have been bound to a reactive function, you can lay out the bound function and the widgets in any order or combination you like, including across Jupyter notebook cells if desired.
The `pn.bind` reactive programming API requires the programmer to select and configure widgets and to lay out components explicitly. Once widgets have been bound to a reactive function, you can lay out the bound function and the widgets in any order or combination you like, including across Jupyter notebook cells if desired.

## Pros:

+ Very clear mapping from widgets to the arguments of the function.
+ Very explicit layout of each of the different components.
+ Like `interact`, doesn't typically require modifying existing visualization code.
+ Clear mapping from widgets to the arguments of the function.
+ Explicit layout of each of the different components.
+ Doesn't typically require modifying existing visualization code.

## Cons:

- Typically requires a bit more code than `interact`
+ Compared to the Declarative API approach, the resulting code is specific to the GUI framework

## Explanation

In this model, we can use an existing plotting function just as for `interact`, but then need to declare each widget explicitly and then bind a widget to each of the arguments that we want to be interactive. The `pn.bind` function works much like [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial) in that it binds regular arguments and keyword arguments to a function. `partial` can only bind specific, static arguments like `5`, but `pn.bind` can also bind parameters, widgets, and other dynamic functions with dependencies to the arguments, ensuring when the function is called the current values of the parameters are passed to the function. A bound function is then reactive, updating whenever the widget values change.
In this model, we can use an existing plotting function, declare each widget explicitly, and then bind a widget to each of the arguments that we want to be interactive. The `pn.bind` function works much like [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial) in that it binds regular arguments and keyword arguments to a function. `partial` can only bind specific, static arguments like `5`, but `pn.bind` can also bind parameters, widgets, and other dynamic functions with dependencies to the arguments, ensuring when the function is called the current values of the parameters are passed to the function. A bound function is then reactive, updating whenever the widget values change.

To make the concept of binding clear, let's look at a trivial example first:

Expand Down Expand Up @@ -58,7 +58,7 @@ pn.Row(
)
```

Notice how here we didn't even need the `autompg_plot` function here, because `bind` works with both methods and functions, so for this particular case the reactive API works out to the same amount of code as the [`interact`](interact) API.
Notice how here we didn't even need the `autompg_plot` function because `bind` works with both methods and functions.

If you are writing code specifically for building an app, and do not wish to keep domain and GUI code separate, the functionality of `pn.bind` is also available as a decorator `@pn.depends`:

Expand Down
2 changes: 1 addition & 1 deletion doc/explanation/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
:hidden:
:maxdepth: 1

API context <api/api_context>
API context <api/index>
```
6 changes: 3 additions & 3 deletions doc/explanation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Beyond the [Getting Started > Core Concepts](../getting_started/core_concepts.md
::::{grid} 1 2 2 3
:gutter: 1 1 1 2

:::{grid-item-card} {octicon}`arrow-both;2.5em;sd-mr-1 sd-animate-grow50` API context
:link: api/api_context
:::{grid-item-card} {octicon}`workflow;2.5em;sd-mr-1 sd-animate-grow50` API context
:link: api/index
:link-type: doc

Learn why there are multiple Panel APIs.
Learn the pros and cons of Panel's different APIs.
:::

::::
Expand Down
68 changes: 0 additions & 68 deletions doc/how_to/apis/examples/stocks_interact.md

This file was deleted.

9 changes: 0 additions & 9 deletions doc/how_to/apis/examples/stocks_plotly.md

This file was deleted.

93 changes: 0 additions & 93 deletions doc/how_to/apis/index.md

This file was deleted.

Loading