Enter a search term above to see results...
On This Page
Templating
Overview
Semantic UI templates compile to an Abstract Syntax Tree (AST) for efficient rendering and targeted DOM updates. The declarative syntax handles async operations, loops, conditionals, and reactive expressions with automatic dependency tracking.
Writing Templates
Flexible Syntax
Template syntax is designed to be adaptable to your team’s preferences and to help components feel more natural across codebases of different languages.
Brackets
Bracket syntax supports either single or double bracket as long as it is consistent across the file.
Welcome, { getFirstName }Welcome, {{ getFirstName }}Expression Styles
Expressions support both Lisp-style (semantic) and JavaScript syntax, even mixed in the same template:
{ formatDate date 'h:mm a' timezone }{ titleCase concat firstName ' ' lastName }{ formatDate(date, 'h:mm a', timezone) }{ users.filter(u => u.active).length }{ formatDate (date + offset) 'h:mm a' {locale: 'en-US'} }Templates compile once per component type and reuse the AST across instances. See Templates & Data Context for integration details.
Binding Data
Templates are bound to a data context which is used for evaluating expressions.
You can think of the data context as “all the variables defined in the scope of your template”.
When using the component framework these will come from sources in your component like their settings, and internal state.
Template Features
Expressions
Evaluate against the template’s data context. Expressions are reactive - they re-evaluate when signals change.
{name}{users.0.email}{formatDate createdAt 'MMM DD'}{#html sanitizedContent}Attribute Expressions
With quotes: always renders as string
<input type="number" value="{count}">Without quotes: removes attribute when falsy
<button disabled={isLoading}>Submit</button>Conditionals
Control flow using #if, #else if, and #else.
{#if isColor 'red'} Red{else if isColor 'blue'} Blue{else} Another color{/if}Loops
Three iteration syntaxes with automatic index/key variables:
Direct context
{#each users} {name} ({index}){/each}Named iterator (each…in)
{#each user in users} {user.name} ({index}){/each}Alternate syntax (each…as)
{#each users as user, idx} {user.name} ({idx}){/each}Object iteration
{#each value, key in settings} {key}: {value}{/each}Empty state
{#each items} {name}{else} No items{/each}Async Operations
Handle promises directly in templates with automatic reactive re-execution:
{#async fetchUser userId as user} <h3>{user.name}</h3>{loading} <div class="spinner">Loading...</div>{error as e} <p>Failed: {e.message}</p>{/async}Reactive dependencies (userId above) trigger automatic refetch.
Reactivity Control
Fine-tune when template sections update:
Force re-evaluation including non-reactive content
{#rerender userId} <p>User: {userName}</p> <p>Timestamp: {getTimestamp}</p>{/rerender}Only re-render when computed value changes
{#guard getUserStatus} <div class="status-{getUserStatus}"> {expensiveComputation} </div>{/guard}Slots
Define areas for external content injection.
Default slot
{>slot}Named slot
{>slot header}Global Helpers
Built-in utilities for formatting, logic, and CSS classes:
{formatDate createdAt 'MMM DD, YYYY'}{capitalize title}{classIf isActive 'active' 'inactive'}{hasAny items}Custom Helpers
Extend the template system:
import { registerHelper } from '@semantic-ui/templating';
registerHelper('timeAgo', (date) => { const seconds = Math.floor((Date.now() - date) / 1000); if (seconds < 60) return 'just now'; if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`; return `${Math.floor(seconds / 3600)}h ago`;});Subtemplates
Compose components and enable template-as-settings patterns:
Simple subtemplate
{> userCard user}With data object
{> userCard name=user.name role='admin'}Dynamic template selection
{>template name=getTemplateName data={user: currentUser}}Separate reactive/non-reactive data
{>template name='userProfile' reactiveData={status: userStatus} // Re-renders on change data={theme: 'dark'} // Static data}Template as Settings
Let consumers provide custom templates:
// Consumer specifies template$('ui-table').settings({ rowTemplate: myCustomRowTemplate});Snippets
Inline reusable fragments - like subtemplates but defined in the same file:
{#snippet userRow} <tr> <td>{name}</td> <td>{role}</td> <td>{formatDate joinDate 'MMM YYYY'}</td> </tr>{/snippet}Use multiple times with different data
{#each admins} {>userRow}{/each}
{#each members} {>userRow}{/each}Snippets inherit parent data context but can receive additional data:
{>userRow extraClass='highlight'}