htm with Preact: render a report without a JSX build step

Render a readable table from JavaScript data while preserving the template and its dependency.

A browser opens your report file and stops at a JSX syntax error. Use htm's tagged templates with Preact when you want to author the report in ordinary JavaScript without a JSX compilation step. Keep the data separate from the template so the same source can produce the next reading copy.

For a fictional packing note, use two supplied rows: Cedar has four boxes and Birch has seven. The report should show both rows and an eleven-box total. This is a document rendering exercise; it does not reserve stock or send an order.

Actual htm and Preact: fictional two-row packing note
Actual htm and Preact: fictional two-row packing note
Open the full example ↗

Open the complete example · Download the full HTML source

Choose the binding before writing the template

The official htm README documents the Preact binding and the combined standalone module. Its combined module exports html and render. The following recipe assumes you have obtained the selected release's combined module and placed it beside your source page as htm-preact.module.js:

<main id="report"></main>
<script type="module">
import { html, render } from './htm-preact.module.js';

const rows = [
  {name: 'Cedar', boxes: 4},
  {name: 'Birch', boxes: 7}
];
const total = rows.reduce((sum, row) => sum + row.boxes, 0);
const report = html`
  <article>
    <h1>Packing note</h1>
    <p>Fictional exercise: ${total} boxes across ${rows.length} rows.</p>
    <table>
      <caption>Supplied box counts</caption>
      <thead><tr><th>Group</th><th>Boxes</th></tr></thead>
      <tbody>${rows.map(row => html`
        <tr key=${row.name}>
          <th scope="row">${row.name}</th><td>${row.boxes}</td>
        </tr>
      `)}</tbody>
    </table>
  </article>`;
render(report, document.querySelector('#report'));
</script>

This is a source recipe, not a complete single-file download. The local module must exist, the page needs its normal document structure and styles, and the chosen browser opening environment must support loading that module. Removing a compiler step does not remove the runtime dependency.

Keep the template tag attached to the markup

The backticks belong to the html tag. An ordinary JavaScript string containing angle brackets is not the same call. The README also shows the more general arrangement, htm.bind(h), when you supply your own element-creation function. Use one documented binding consistently rather than mixing a React binding into a Preact example.

The component syntax also differs from an HTML tag whose name is fixed in the source. htm documents component references such as <${Component}>. For this small table, ordinary authored elements are enough; a component abstraction would add another thing for the next editor to locate.

Check the rendered document against the rows

Calculate the expected total from the supplied values before accepting the rendered page: four plus seven is eleven. Read both row labels and counts in the finished table. A correct total alone would not catch two swapped labels.

Then make a deliberate source edit: change Birch from seven to two. The next render should show four and two with a six-box total. Restore the original fixture afterward. The complete example was rendered with the htm 3.1.1 combined Preact module: the original rows produced eleven, the edited rows produced six, and restoring the original rows produced eleven again. The example keeps that selected distribution inline; the short source recipe above instead illustrates a neighboring module.

Keep the total in normal text and the values in a table. A reader should not need an application console or an unseen JavaScript object to recover the supplied numbers. At phone width, check the heading, caption, row labels, and counts in their reading order.

The existing petite-vue estimate attaches expressions to an already authored HTML region and validates an editable tray input. This task creates the report tree from JavaScript values using htm's Preact binding. Its useful output is a rendered document, so it needs no artificial submission button.

Package the dependency with the source

Retain the exact htm/Preact distribution used to render the page, the source rows, and the maintained template. The self-contained HTML checklist explains why a neighboring module does not travel inside an HTML attachment. If the delivery requirement is one file, prepare a compatible embedded distribution and test that resulting file separately.

End the handoff with the accepted counts and the source that produced them. When the numbers change, edit the rows and render the report again; do not correct only the visible total while leaving its table and source behind.

Keep reading