HTML Templates — HTMQL Documentation

HTML Templates

Standard HTML content can be included in the HTML section of a page. The application server uses Go's HTML Template library to dynamically generate the HTML content using available data from the SQL commands.

See https://pkg.go.dev/text/template for more details on the HTML template library.

Template Data

Data values are applied to the template using the {{.field}} syntax.

The rows and fields returned by SQL commands are available as template data under .<alias>. Aliases are always lowercase in template data, even if defined with uppercase characters. Field names must match the casing of the database column name exactly.

By default, every alias returns an array of rows, which must be accessed via {{ range .<alias> }}. The range must have a matching {{end}}. Everything inside the range will be repeated for each SQL record. Inside the range, each field is available as {{ .<fieldname> }}

For example:

{{range .select}}
    <tr>
        <td>{{.id}}</td>
        <td>{{.name}}</td>
    </tr>
{{end}}
Single Record Results

Aliases can be defined as singular by prefixing the alias with a $, which eliminates the need to use {{ range }} when accessing the command results. This is ideal for a query that you know will always return a single row, such as on a page that returns the data for a single item. If multiple rows are returned by a command marked as singular, only the first row is available in the template.

For example:

<h1>{{.select.name}}</h1>
Metadata

Metadata about the alias SQL command is available as template data under .<alias>_data. The following fields are available:

  • command is the SQL command that was passed to the database engine
  • exec returns a boolean indicating if the alias was executed on the database engine (e.g. will be false if didn't run due to missing parameter, or if previous critical command failed and stopped execution before this alias was executed)
  • error returns the text of any error messages returned by the commands in the alias. If the text is blank, either no error occurred or it did not execute. If the length is greater than 0 then the command executed and failed.
  • count returns the # of rows returned

For example:

<ul>
  <li>SQL Command: {{.select_data.command}}</li>
  <li>Was Executed? {{.select_data.exec}}</li>
  <li>SQL Errors: {{.select_data.error}}</li>
  <li>SQL Records Returned: {{.select_data.count}}</li>
</ul>

Template Control Structure

The following control structures are available in the HTML template:

  • {{if <condition>}} - Uses the <condition> to decide if the block should be rendered.
  • {{range .<alias>}} - Renders the block for each row returned by the SQL command with the name <alias>.
  • {{define "<name>"}} - Defines a reusable block that can be referenced in other parts of the file.
  • {{else}} - Renders as the alternative block if the if condition was false or no rows were found in the range.
  • {{end}} - Ends an if or range or define block.
  • {{/* <comment> */}} - Adds a comment to the template.
  • {{break}} - Breaks out of the current range block.
  • {{continue}} - Stops iterating the current range block and continues to the next record.
  • {{template "<name>" [.data]}} - See the Reusable HTML Templates section below.
Conditions

Conditions can be a data value (e.g. .alias.field) or a function described below. Conditions evaluate to either true or false. Empty and missing values are considered false.

Template Functions

All functions follow the format of <function name> [parameter n...] . Parameters can be wrapped in parentheses to allow stacking of functions, e.g. {{if and (eq method "GET") (eq username .field1)}}.

Logic Functions
  • and <x> <y> - Returns the boolean AND of its arguments by returning the first empty argument or the last argument. That is, "and x y" behaves as "if x then y else x". Evaluation proceeds left to right and returns when the result is determined.
  • len <x> - Returns the integer length of the string or array x.
  • js <x> - Returns the JavaScript-escaped string x.
  • not <x> - Returns the boolean NOT of its argument.
  • or <x> <y> - Returns the boolean OR of its arguments by returning the first non-empty argument or the last argument. That is, "or x y" behaves as "if x then x else y". Evaluation proceeds left to right and returns when the result is determined.
Comparison Functions
  • eq <x> <y> - Returns true if x is equal to y.
  • ne <x> <y> - Returns true if x is not equal to y.
  • lt <x> <y> - Returns true if x is less than y.
  • le <x> <y> - Returns true if x is less than or equal to y.
  • gt <x> <y> - Returns true if x is greater than y.
  • ge <x> <y> - Returns true if x is greater than or equal to y.
Application Functions
  • method - returns the current HTTP method: GET, POST, PUT, PATCH, or DELETE
  • route - returns the URL path of the current page (e.g. for generating links back to this page)
  • slugname - returns the name of the slug variable in the route
  • slug - returns the value of the slug; returns a blank string if no slug is used
  • param <name> - returns a query parameter value as a string. Use string comparison operators (e.g. eq) when comparing in templates.
  • pathescape <url path> - escapes a single URL path segment (e.g. %Test Page%25Test%20Page)
  • queryescape <url> - escapes a value for use in a URL query string
  • username - returns the authenticated user's username, or ANONYMOUS if not authenticated
  • displayname - returns the authenticated user's display name, or ANONYMOUS if not authenticated
  • role <name> - returns true if the authenticated user literally has the specified role
  • notrole <name> - returns true if the authenticated user does not have the specified role
  • auth <name...> - returns true if the user is authorized for any of the given roles (mirrors page-policy allow semantics: honors auth.adminRole, the reserved public/auth roles, and accepts multiple comma-separated or separate-argument roles)
  • notauth <name...> - the negation of auth
String Formatting Functions
  • date <value> - returns the value formatted as YYYY-MM-DD
  • isodate <value> - returns the value formatted as YYYY-MM-DD
  • sdate <value> - returns the value formatted with the configured short date format (default YYYY-MM-DD)
  • ldate <value> - returns the value formatted with the configured long date format (default DDD MMM D YYYY)
  • isotime <value> - returns the value formatted as HH:MM:SS
  • time <value> - returns the value formatted with the configured time format (default H:MMTT)
  • isodtime <value> - returns the value formatted as YYYY-MM-DD HH:MM:SS
  • sdtime <value> - returns the value formatted with the configured short date and time format (default YYYY-MM-DD H:MMTT)
  • ldtime <value> - returns the value formatted with the configured long date and time format (default DDD MMM D YYYY H:MMTT)
  • num <value> - returns the value formatted with the configured number format (default 0,000)
  • dec <value> - returns the value formatted with the configured decimal format (default 0,000.0)
  • ldec <value> - returns the value formatted with the configured long decimal format (default 0,000.0000)
  • money <value> - returns the value formatted with the configured money format (default $0,000.00)
  • fmt <value> <format> - returns the value formatted with the defined format
  • format <value> <format> - same as fmt above
  • fdate <value> <format> - returns the date value formatted with the defined format
  • fnum <value> <format> - returns the numeric value formatted with the defined format
  • br <value> - converts CR, LF, and CRLF line breaks into HTML <br/> tags
  • str <value> - converts any value to a string
  • markdown <value> - renders a Markdown string as sanitized HTML (GitHub Flavored Markdown). md is an alias. See Markdown editor and rendering.

The default formats can be overridden using the following settings underneath the formatting section of the configuration file:

  • shortDate - the format for short dates
  • longDate - the format for long dates
  • time - the format for times
  • shortDateTime - the format for short date and time
  • longDateTime - the format for long date and time
  • numbers - the format for numbers
  • decimals - the format for decimals
  • longDecimals - the format for long decimals
  • money - the format for money

Reusable HTML Templates

You can make re-usable "components" by creating .html files in the templates folder. These HTML files will be available in pages using {{ template "<filename.html>" }}. These template files are not parsed for SQL commands.

You can make data from the page available to the sub-template, e.g. {{ template "filename.html" .select }}

Slugs are not available in templates, only in pages.

Markdown Editor and Rendering

HTMQL supports authoring rich text as Markdown while keeping Markdown as the single source of truth in the database. Markdown is stored in a plain column; HTML is generated on demand and never stored. There are two halves:

1. WYSIWYG editing (client-side). The bundled Toast UI Editor (MIT) provides a what-you-see-is-what-you-get editor that reads and writes Markdown. It is wired to a hidden <textarea> by the reusable md-editor.html template, so the Markdown submits as an ordinary form field - no special server handling is needed.

{{/*
@id=0
GET:$record:SELECT id, notes FROM article WHERE id=@id;
POST:!!save:UPDATE article SET notes=@notes WHERE id=@id;
*/}}

<form hx-post="{{route}}">
  <input type="hidden" name="id" value="{{.record.id}}" />
  <textarea name="notes" data-md-editor>{{.record.notes}}</textarea>
  {{template "md-editor.html" .}}
  <button type="submit">Save</button>
</form>

The textarea's content seeds the editor (Markdown), and the editor writes Markdown back into the textarea on every change. Include the md-editor.html snippet once per page. Per-editor options are set with data-* attributes on the textarea:

  • data-md-height - editor height (default 400px)
  • data-md-mode - initial tab, wysiwyg (default) or markdown

2. Rendering Markdown → HTML (server-side). The markdown template function (alias md) converts a stored Markdown string into sanitized HTML using goldmark (GitHub Flavored Markdown) with output run through bluemonday so authored content cannot inject unsafe markup:

<article>{{markdown .record.notes}}</article>

The same renderer powers the email body_format=markdown option, so Markdown authored in the editor can be emailed as a proper HTML body without duplicating any conversion logic.