Skip to content

Commit

Permalink
Allow building ESM based components (#5593)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored Jun 21, 2024
1 parent cd9e0c5 commit 94066c9
Show file tree
Hide file tree
Showing 95 changed files with 8,068 additions and 585 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,5 @@ app_streamlit.py
pixi.lock
panel/_version.py
.uicoveragerc
mario_button.*
counter_button.*
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@
'galleries': {
'reference': {
'title': 'Component Gallery',
'extensions': ['*.ipynb', '*.py', '*.md'],
'sections': [
'panes',
'widgets',
'layouts',
# 3 most important by expected usage. Rest alphabetically
'chat',
'custom_components',
'global',
'indicators',
'templates',
Expand Down
72 changes: 72 additions & 0 deletions doc/how_to/custom_components/esm/callbacks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ESM component with callback

In this guide we will show you how to add callbacks to your ESM components.

## Slideshow with Python callback

This example shows you how to create a `SlideShow` component that uses a Python *callback* function to update the `Slideshow` image when its clicked:

```{pyodide}
import param
import panel as pn
from panel.custom import JSComponent
pn.extension()
class Slideshow(JSComponent):
index = param.Integer(default=0)
_esm = """
export function render({ model }) {
const img = document.createElement('img')
img.src = `https://picsum.photos/800/300?image=${model.index}`
img.addEventListener('click', (event) => model.send_event('click', event))
model.on('index', () => {
img.src = `https://picsum.photos/800/300?image=${model.index}`
})
return img
}
"""
def _handle_click(self, event):
self.index += 1
Slideshow(width=500, height=200).servable()
```

This approach lets you quickly build custom components with complex interactivity. However if you do not need any complex computations in Python you can also construct a pure JS equivalent:

## Slideshow with Javascript Callback

This example shows you how to create a `Slideshow` component that uses a Javascript *callback* function to update the `Slideshow` image when its clicked:

```{pyodide}
import param
import panel as pn
from panel.custom import JSComponent
pn.extension()
class JSSlideshow(JSComponent):
index = param.Integer(default=0)
_esm = """
export function render({ model }) {
const img = document.createElement('img')
img.src = `https://picsum.photos/800/300?image=${model.index}`
img.addEventListener('click', (event) => { model.index += 1 })
model.on('index', () => {
img.src = `https://picsum.photos/800/300?image=${model.index}`
})
return img
}
"""
JSSlideshow(width=800, height=300).servable()
```

By using Javascript callbacks instead of Python callbacks you can achieve higher performance, components that can be *js linked* and components that will also work when your app is saved to static html.
Loading

0 comments on commit 94066c9

Please sign in to comment.