Motivation¶
Dash is an excellent way to build React-powered single-page apps in Python. When building some dashboards, I found myself making a lot of mistakes [1] like this:
app.layout = html.Div([
html.Table(style={"margin": "0 auto"}, children=[
html.Tr(html.Th("char"), html.Th("name"), html.Th("category"))
] + [
html.Tr(
[html.Td(char),
html.Td(unicodedata.name(char, '???')),
html.Td(unicodedata.category(char))],
style={'background-color': '#eee' if line % 2 else '#ccc'}
)
for line, char in enumerate(chr(i) for i in range(32, 128))
])
])
An obvious idea would be to use a templating language such as Jinja:
<div>
<table style="margin: 0 auto;">
<tr><th>char</th><th>name</th><th>category</th></tr>
{% for i in range(32, 128) %}
<tr style="background-color: {{ loop.cycle('#eee', '#ccc') }}">
<td>{ i | chr }</td>
<td>{ i | getname }</td>
<td>{ i | getcategory }</td>
</tr>
{% endfor %}
</table>
</div>
assuming suitable filters for the Unicode lookups. But this doesn’t work with Dash, because Jinja produces HTML while Dash builds a React app from the component tree.
The htexpr package allows a similar syntax, with embedded Python for templating but a Dash component tree as the output:
app.layout = htexpr.compile("""
<div>
<table style={"margin": "0 auto"}>
<tr><th>char</th><th>name</th><th>category</th></tr>
[
(<tr style={'background-color': '#eee' if line % 2 else '#ccc'}>
<td>{ char }</td>
<td>{ unicodedata.name(char, '???') }</td>
<td>{ unicodedata.category(char) }</td>
</tr>)
for line, char in enumerate(chr(i) for i in range(32, 128))
]
</table>
</div>
""").run()
[1] | The File ".../dash/development/base_component.py", line 244, in _traverse_with_paths
"(id={:s})".format(i.id)
TypeError: unsupported format string passed to Th.__format__
|