Basic Usage

Use the following imports (the exact aliases dcc and html are default values in the htexpr configuration):

import dash
from dash import dcc, html
from dash import table as dash_table
import htexpr

When building your Dash app, instead of instantiating objects like html.Div you can now write HTML in a string that is compiled and evaluated by htexpr:

app = dash.Dash()
app.layout = htexpr.compile("""
  <div class="c">
    <Input id="i" type="number" />
  </div>
""").run()

This has the same effect as instantiating the objects directly:

app.layout = html.Div(
    className="c",
    children=[
        dcc.Input(id="i", type="number", children=[])
    ]
)

In addition to compiling HTML, you can embed Python code, which itself can include HTML in parentheses:

from pathlib import Path
name = "A Fine Dashboard"
h1_class = "heading"
app.layout = htexpr.compile("""
  <div>
    <header>
      <h1 class={ h1_class }
          style={"font-size": "x-large", "background": "#8899aa"}
         >{ name }</h1>
    </header>
    <h2>Files</h2>
    <ul>
      <li>. (the current directory)</li>
      <li>.. (the parent directory)</li>
      [ (<li>{ str(file) }</li>)
        for file in Path('.').glob('*')
        if file.is_file() ]
    </ul>
  </div>
""").run()

Several substitutions of Python code occur:

  • In <h1 class={ h1_class }>, the class attribute gets the value of the id variable. Because class is not a legal Python identifier, the H1 component actually takes an argument named className, so htexpr translates the HTML class attribute to the className argument.
  • In <h1 style={...}>, the style attribute has a value that is a Python dictionary. The H1 component (and all others) accept a dictionary for the style argument.
  • In <h1>{ name }</h1>, the element contains the value of the name variable.
  • In <ul>[ (<li>...</li>) for file in Path('.').glob('*') ]</ul>, the list items are generated from a list comprehension. Note that the list item element must be placed in parentheses to allow the htexpr parser to detect it.
  • Each list item (<li>{ str(file) }</li>) is generated by calling the Python function str on the comprehension variable file.

The rules are:

  • Use any of Dash’s HTML or core components, or DataTable. HTML elements may be typed in any case (<H1> or <h1>), other components must be in the exact case defined by Dash (<Dropdown>, not any other spelling).

  • Close all elements with either a closing tag or a self-closing tag: <ul>...</ul> or <input /> are both fine.

  • Enclose literal attribute values in single or double quotes: <span id='foo' class="bar" />.

  • Enclose Python code in braces in either attribute values or inside elements. For attributes such as style that take a dictionary, it is enough to use one layer of braces.

  • You can also write list comprehensions in square brackets, and the results are spliced at the same level as neighboring elements. Thus the file list in the preceding example has the static items for . and .. at the same level as the dynamically generated items.

  • Some attribute names are transformed, because they are either invalid identifiers or React developers prefer camel case:

    HTML React
    class className
    accesskey accessKey
    hreflang hrefLang
    contenteditable contentEditable
    tabindex tabIndex
    colspan colSpan
    rowspan rowSpan
    spellcheck spellCheck
    for htmlFor

    In all cases, htexpr translates the HTML spelling to the React spelling, which is understood by Dash components.

  • The HTML elements Map and Object are translated to MapEl and ObjectEl, respectively.