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

ReactiveHTML loop not working if option tag not included #2682

Closed
MarcSkovMadsen opened this issue Aug 28, 2021 · 3 comments
Closed

ReactiveHTML loop not working if option tag not included #2682

MarcSkovMadsen opened this issue Aug 28, 2021 · 3 comments
Labels
type: bug Something isn't correct or isn't working

Comments

@MarcSkovMadsen
Copy link
Collaborator

MarcSkovMadsen commented Aug 28, 2021

I'm on Panel 0.12.1.

While trying to create an Accordion Layout from the ReactiveHTML I could not get the jinja loop working without including the <option id="option"> tag.

For example when creating a layout my list of panels are not options. They are just a list of panels to be inserted.

Works - Using option tag

I'm using

    _template = """
{% for obj in objects %}<option id="option">${obj}</option>{% endfor %}
"""

and it works

image

import panel as pn
import param

pn.extension("vega", sizing_mode="stretch_width")

class FastAccordion(pn.reactive.ReactiveHTML):
    objects = param.List()


    _template = html ="""
{% for obj in objects %}<option id="option">${obj}</option>{% endfor %}
"""

    def __init__(self, *objects, **params):
        params["objects"]=[pn.panel(obj) for obj in objects]
        super().__init__(**params)

component1 = pn.Column("a", pn.Spacer(background="blue"),
    background="yellow", name="Component 1")
vegalite = {
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "data": {"url": "https://raw.githubusercontent.com/vega/vega/master/docs/data/barley.json"},
  "mark": "bar",
  "encoding": {
    "x": {"aggregate": "sum", "field": "yield", "type": "quantitative"},
    "y": {"field": "variety", "type": "nominal"},
    "color": {"field": "site", "type": "nominal"},
  },
  "width": 'container',
}
vgl_pane = pn.panel(vegalite, height=240)

accordion = FastAccordion(component1, vgl_pane, "d")

pn.template.FastListTemplate(
    title="Awesome Panel",
    main = [accordion, vgl_pane],
    main_layout="",
).servable()

Does not work - Not Using option tag

If I use the template

_template = """
{% for obj in objects %}${obj}{% endfor %}
"""

I see

2021-08-28 08:29:33,155 error handling message
 message: Message 'PULL-DOC-REQ' content: {}
 error: TypeError('Object of type Column is not JSON serializable')
Traceback (most recent call last):
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\server\protocol_handler.py", line 90, in handle
    work = await handler(message, connection)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\server\session.py", line 67, in _needs_document_lock_wrapper
    result = func(self, *args, **kwargs)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\server\session.py", line 232, in _handle_pull
    return connection.protocol.create('PULL-DOC-REPLY', message.header['msgid'], self.document)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\protocol\__init__.py", line 85, in create
    return self._messages[msgtype].create(*args, **kwargs)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\protocol\messages\pull_doc_reply.py", line 74, in create
    content = { 'doc' : document.to_json() }
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\document\document.py", line 902, in to_json
    doc_json = self.to_json_string()
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\document\document.py", line 959, in to_json_string
    return serialize_json(json, indent=indent)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\core\json_encoder.py", line 166, in serialize_json
    return json.dumps(obj, cls=BokehJSONEncoder, allow_nan=False, indent=indent, separators=separators, sort_keys=True, **kwargs)
  File "C:\Python38\lib\json\__init__.py", line 234, in dumps
    return cls(
  File "C:\Python38\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Python38\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\core\json_encoder.py", line 261, in default
    return self.transform_python_types(obj)
  File "c:\repos\private\awesome-panel-introduction\.venv\lib\site-packages\bokeh\core\json_encoder.py", line 228, in transform_python_types
    return super().default(obj)
  File "C:\Python38\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Column is not JSON serializable
import panel as pn
import param

pn.extension("vega", sizing_mode="stretch_width")

class FastAccordion(pn.reactive.ReactiveHTML):
    objects = param.List()


    _template = """
{% for obj in objects %}${obj}{% endfor %}
"""

    def __init__(self, *objects, **params):
        params["objects"]=[pn.panel(obj) for obj in objects]
        super().__init__(**params)

component1 = pn.Column("a", pn.Spacer(background="blue"),
    background="yellow", name="Component 1")
vegalite = {
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "data": {"url": "https://raw.githubusercontent.com/vega/vega/master/docs/data/barley.json"},
  "mark": "bar",
  "encoding": {
    "x": {"aggregate": "sum", "field": "yield", "type": "quantitative"},
    "y": {"field": "variety", "type": "nominal"},
    "color": {"field": "site", "type": "nominal"},
  },
  "width": 'container',
}
vgl_pane = pn.panel(vegalite, height=240)

accordion = FastAccordion(component1, vgl_pane, "d")

pn.template.FastListTemplate(
    title="Awesome Panel",
    main = [accordion, vgl_pane],
    main_layout="",
).servable()

Additional Context

Inserting the option tag bloats the html and could make it difficult to control the layout and style.

@MarcSkovMadsen MarcSkovMadsen added TRIAGE Default label for untriaged issues type: bug Something isn't correct or isn't working and removed TRIAGE Default label for untriaged issues labels Aug 28, 2021
@philippjfr
Copy link
Member

So the whole point of the loop syntax is that you use it when you want some custom tag to wrap each child. Indeed the documentation makes this part pretty clear (imo):

However if you want to wrap each child in some custom HTML you will have to use Jinja2 loop syntax:

If you really just want to insert each child without wrapping it the regular syntax is what you should use:

<div id="div">${children_parameter}</div>

@philippjfr
Copy link
Member

Happy to improve documentation around this if you have suggestions.

@philippjfr
Copy link
Member

Okay, improved the documentation in #2689

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't correct or isn't working
Projects
None yet
Development

No branches or pull requests

2 participants