Details¶
Configuration¶
The preceding discussion assumes you import Dash packages under the usual names:
from dash import html, dcc
from dash import table as dash_table
If this does not match your preferences, you can customize the mappings used by htexpr:
from dash import html as H
from dash import dcc as C
import htexpr
from htexpr import mappings
tags = [mappings.html('H'), mappings.dcc('C')]
def compile(code):
return htexpr.compile(code, map_tag=tags)
There is a prebuilt configuration for Dash Bootstrap components:
from dash import html, dcc
import dash_bootstrap_components as dbc
import htexpr
from htexpr import mappings
def compile(code):
return htexpr.compile(code, map_tag=mappings.dbc_and_default)
layout = compile("""
<Container class="p-5"><Alert>Hello Bootstrap!</Alert></Container>
""").run()
The Bootstrap components shadow some HTML components, but there is a trick to work around this: if you need to use an HTML component, just use upper/lowercase letters differently from the Bootstrap components.
compile("""
<div>
<Label>this is a Bootstrap label</Label>
<label>this is an HTML label</label>
</div>
""")
Htexpr objects¶
The compile
function returns an Htexpr
object, which
encapsulates the Python code resulting from the compilation. This
object needs to be evaluated to result in actual Dash objects. Because
the Python code refers to various objects (such as imported modules,
functions, and variables) these need to be passed in:
from dash import html
htexpr.compile(
"<div>[(<span>{i}</span>) for i in range(10) if i not in removed]</div>"
).eval({**globals(), "removed": {1, 2, 3}})
The compiled code is able to refer to html.Div
because html
occurs in globals()
, and to the removed
variable because it is
included in the bindings manually. Similarly, local variables can be
included with **locals()
.
Including **globals()
and **locals()
every time gets tedious,
so there is a small magic trick to do it automatically:
from dash import html
htexpr.compile(
"<div>[(<span>{i}</span>) for i in range(10) if i not in removed]</div>"
).run(removed={1, 2, 3})
The run
method peeks into the caller’s frame and automatically
includes all the global and local bindings. Any keyword arguments are
added on top of these.
Peeking into frames is discouraged by some Python developers and
involves calling a private function, so the eval
method is
recommended for anyone who is worried.