Declarative HTML
Build complex UIs with zero JavaScript using data-tx-widget attributes and tx-* child elements.
How It Works
On DOMContentLoaded, Teryx scans the document for data-tx-widget elements and instantiates widgets. A MutationObserver watches for dynamically added elements too.
<div data-tx-widget="grid" data-tx-source="/api/users" data-tx-paginated data-tx-searchable>
<tx-column field="name" label="Name" sortable></tx-column>
<tx-column field="email" label="Email"></tx-column>
<tx-column field="role" label="Role" filterable></tx-column>
</div>
data-tx-* Attributes
Options are passed as data-tx-* attributes, converted from kebab-case to camelCase:
<div data-tx-widget="grid"
data-tx-source="/api/users"
data-tx-page-size="25"
data-tx-paginated
data-tx-searchable>
</div>
Type Coercion
- Boolean:
sortable,required,disabledetc. aretruewhen present - Numeric:
"25"becomes25 - JSON: Values starting with
[or{are parsed - Everything else stays a string
tx-column
Grid columns as child elements:
<div data-tx-widget="grid" data-tx-source="/api/products">
<tx-column field="name" label="Product" sortable width="200px"></tx-column>
<tx-column field="price" label="Price" align="right" renderer="number"></tx-column>
<tx-column field="status" label="Status" filterable filter-type="select"
filter-options='[{"label":"Active","value":"active"},{"label":"Archived","value":"archived"}]'>
</tx-column>
</div>
| Attribute | Type | Description |
|---|---|---|
field | string | JSON field name |
label | string | Header text |
sortable | boolean | Enable sorting |
width | string | Fixed width |
renderer | string | Built-in renderer (text, number, date, boolean, badge, link, progress, actions) |
filterable | boolean | Column filter |
editable | boolean | Inline editing |
tx-field
Form fields:
<div data-tx-widget="form" data-tx-action="/api/contact" data-tx-layout="vertical">
<tx-field name="name" label="Full Name" required></tx-field>
<tx-field name="email" label="Email" type="email" required></tx-field>
<tx-field name="dept" label="Department" type="select"
options='[{"label":"Engineering","value":"eng"},{"label":"Sales","value":"sales"}]'>
</tx-field>
<tx-field name="message" label="Message" type="textarea" rows="4"></tx-field>
</div>
tx-tab
Tab panels with inline content:
<div data-tx-widget="tabs" data-tx-variant="underline">
<tx-tab title="Overview"><p>Overview content.</p></tx-tab>
<tx-tab title="Settings" icon="settings"><p>Settings panel.</p></tx-tab>
</div>
tx-item / tx-step
Accordion panels, steps, and list-like widgets:
<div data-tx-widget="accordion" data-tx-multiple>
<tx-item title="Section A" open><p>Content A.</p></tx-item>
<tx-item title="Section B"><p>Content B.</p></tx-item>
</div>
<div data-tx-widget="steps" data-tx-current="1">
<tx-step title="Plan" description="Choose a tier"></tx-step>
<tx-step title="Pay" description="Billing info"></tx-step>
<tx-step title="Confirm" description="Review"></tx-step>
</div>
tx-node
Nested tree nodes:
<div data-tx-widget="tree" data-tx-selectable data-tx-lines>
<tx-node text="Documents" icon="folder" expanded>
<tx-node text="report.pdf" leaf></tx-node>
<tx-node text="slides.pptx" leaf></tx-node>
</tx-node>
</div>
Child Element Reference
| Tag | Maps To | Used By |
|---|---|---|
<tx-column> | columns | grid |
<tx-field> | fields | form |
<tx-tab> | items | tabs |
<tx-item> | items | accordion, sidebar, segmented, navbar |
<tx-step> | items | steps |
<tx-slide> | slides | carousel |
<tx-node> | nodes | tree |
<tx-button> | buttons | modal |
<tx-tier> | tiers | pricing |
<tx-quote> | quotes | testimonials |
<tx-feature> | items | features |
<tx-event> | events | calendar |
<tx-series> | series | chart |
<tx-option> | options | form fields |
<tx-link> | links | footer |
<tx-social> | social | footer |
<tx-toolbar> | toolbar | grid |
<tx-menu-item> | contextMenu | grid |
Boolean Attributes
sortable, required, disabled, readonly, hidden, checked, multiple,
closable, active, open, expanded, leaf, collapsible, collapsed,
searchable, paginated, striped, hoverable, bordered, compact,
selectable, filterable, editable, resizable, draggable, sticky,
animated, dismissible, pill, outline, block, loading
Manual Initialization
import { configure, initWidgets } from 'teryx';
configure({ autoInit: false });
// Later:
initWidgets(document.getElementById('container'));
The declarative API produces the same output as the imperative API. Mix both freely.