Example of using Template with param classes

Just wanted to share an example of how to use Template with param classes.

Let me know if there’s a better way to include the template in the param class (e.g. if there’s a built-in way template=‘React’)

This combines code from https://panel.holoviz.org/user_guide/Param.html and https://panel.holoviz.org/reference/templates/React.html#templates-gallery-react

import panel as pn
import param
pn.extension()
pn.config.sizing_mode = 'stretch_both'


class GoogleMapViewer(param.Parameterized):
    
    continent = param.ObjectSelector(default='Asia', objects=['Africa', 'Asia', 'Europe'])
    
    country = param.ObjectSelector(default='China', objects=['China', 'Thailand', 'Japan'])
    
    _countries = {'Africa': ['Ghana', 'Togo', 'South Africa', 'Tanzania'],
                  'Asia'  : ['China', 'Thailand', 'Japan'],
                  'Europe': ['Austria', 'Bulgaria', 'Greece', 'Portugal', 'Switzerland']}
    
    @param.depends('continent', watch=True)
    def _update_countries(self):
        countries = self._countries[self.continent]
        self.param['country'].objects = countries
        self.country = countries[0]

    @param.depends('country')
    def view(self):
        iframe = """
        <iframe width="100%" height="400px" src="https://maps.google.com/maps?q={country}&z=6&output=embed"
        frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>
        """.format(country=self.country)
        return pn.pane.HTML(iframe, sizing_mode='stretch_both')


viewer = GoogleMapViewer(name='Google Map Viewer')
react = pn.template.ReactTemplate()
react.sidebar.append(viewer.param)
react.main[:, :] = viewer.view
react.servable()
2 Likes

Thanks @ahuang11

This is a great example of the use of the new Templates. The only thing I personally would change is the iframe to to <iframe width="100%"… Then it becomes responsive.

1 Like

I was actually trying to do that with sizing_mode but no avail since I didn’t look at the actual URL!

I worked a little bit with it in order to add it to awesome-panel.org. I primarely changed to code to update the .object of the HTML pane instead of the HTML pane it self to avoid to much “flickr” on the screen when changing the selection. And then I used the FastGridTemplate that I use at awesome-panel.org. This is already pretty mature. But I have many ideas for improving it.

"""In [Discourse 1533]\
(https://discourse.holoviz.org/t/example-of-using-template-with-param-classes/1533) Andrew
showcased this example of using the ReactTemplate with Google Maps

Here it is reproduced using the `FastGridTemplate`
"""
import panel as pn
import param
from application.config import site
from awesome_panel_extensions.frameworks.fast.templates import FastGridTemplate

class GoogleMapViewer(param.Parameterized):

    continent = param.ObjectSelector(default='Asia', objects=['Africa', 'Asia', 'Europe'])

    country = param.ObjectSelector(default='China', objects=['China', 'Thailand', 'Japan'])

    settings_panel = param.Parameter()
    map_panel = param.Parameter()

    _countries = {'Africa': ['Ghana', 'Togo', 'South Africa', 'Tanzania'],
                  'Asia'  : ['China', 'Thailand', 'Japan'],
                  'Europe': ['Austria', 'Bulgaria', 'Greece', 'Portugal', 'Switzerland']}

    def __init__(self, **params):
        super().__init__(**params)
        self.settings_panel = pn.Param(self, parameters=["continent", "country"])
        self.map_panel=pn.pane.HTML(sizing_mode='stretch_width', height=616, margin=0)
        self._update_map()

    @param.depends('continent', watch=True)
    def _update_countries(self):
        countries = self._countries[self.continent]
        self.param['country'].objects = countries
        self.country = countries[0]

    @param.depends('country', watch=True)
    def _update_map(self):
        iframe = """
        <iframe width="100%" height="100%" src="https://maps.google.com/maps?q={country}&z=6&output=embed"
        frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>
        """.format(country=self.country)
        self.map_panel.object = iframe

def view():
    pn.config.sizing_mode="stretch_width"
    viewer = GoogleMapViewer(name='Google Map Viewer')
    template = FastGridTemplate(title="Google Map Viewer", row_height=100)
    template.sidebar.append(viewer.settings_panel)
    template.main[0:6,:]=viewer.map_panel
    return template

if __name__.startswith("bokeh"):
    view().servable()
2 Likes

I can see others have problems with iframe flickr/ blinking and solved it using javascript. https://stackoverflow.com/questions/13396885/how-to-stop-the-iframes-from-blinking