renderHtml Service
The renderHtml
service provides a safe and powerful way to render HTML content with automatic escaping, template literal support, and advanced value resolution.
Interface
The service creates a function that can be called in two ways:
Template Literal Syntax (Primary Usage)
this.renderHtml`<div>Content here</div>`
Function Call Syntax
this.renderHtml(value1, value2, ...)
Description
The renderHtml
service is a template rendering utility built on top of the Html
class that:
- Automatically escapes values to prevent XSS attacks by converting special characters (
&
,<
,>
,"
) to HTML entities - Supports template literals with interpolated values using tagged template syntax
- Resolves complex values including promises, arrays, functions, and objects with
toHtml()
methods - Handles conditional rendering with support for
false
,undefined
, andnull
values (renders as empty string) - Processes nested structures by recursively resolving arrays and callable values
The service is available on all views via this.renderHtml
and is automatically added to the client-side context.
Key Features
- XSS Protection: All interpolated values are automatically escaped unless they are already
Html
instances - Async Resolution: Supports promises and async functions in interpolated values
- Array Handling: Arrays are flattened and joined automatically
- Function Support: Functions are called and their return values are processed
- Object Integration: Objects with
toHtml()
methods are properly integrated - Conditional Logic: Falsy values (
false
,undefined
,null
) render as empty strings
Examples
Basic HTML Rendering
// Simple HTML with escaped content
this.renderHtml`<h1>${title}</h1>`
// With attributes
this.renderHtml`<div class="${className}" id="${elementId}">Content</div>`
Conditional Rendering
// Conditional attributes
this.renderHtml`<input ${disabled ? this.renderHtml`disabled` : ''} />`
// Conditional content blocks
${isAdmin ? this.renderHtml`
<div class="admin-panel">
<a href="/admin">Admin Dashboard</a>
</div>
` : ''}
Array and List Rendering
// Rendering lists
this.renderHtml`
<ul>
${items.map(item => this.renderHtml`
<li>${item.name}</li>
`)}
</ul>
`
// Table rows
${rows.map(row => this.renderHtml`
<tr>
${columns.map(column => this.renderHtml`
<td>${column.cell(row)}</td>
`)}
</tr>
`)}
Complex Nested Structures
// Nested rendering with functions
this.renderHtml`
<section>
${() => {
if(user.isAdmin) {
return this.renderHtml`
<div class="admin-tools">
${adminActions.map(action => this.renderHtml`
<button onclick="${action.handler}">${action.label}</button>
`)}
</div>
`;
}
return this.renderHtml`<p>Access denied</p>`;
}}
</section>
`
Form Elements with Dynamic Attributes
// Select with dynamic options
this.renderHtml`
<select name="${fieldName}">
${Object.entries(options).map(([value, label]) => this.renderHtml`
<option value="${value}"${value == selectedValue ? this.renderHtml` selected="selected"` : ''}>${label}</option>
`)}
</select>
`
// Input with conditional attributes
this.renderHtml`
<input
type="text"
name="${name}"
${placeholder ? this.renderHtml`placeholder="${placeholder}"` : undefined}
${component ? this.renderHtml`data-component="${component}"` : undefined}
class="${baseClass}${error ? ` ${errorClass}` : ''}"
/>
`
Function Call Syntax for JSON Data
// Rendering JSON data safely
this.renderHtml`
<script type="application/json">
${this.renderHtml(JSON.stringify(data))}
</script>
`
// In JavaScript contexts
this.renderHtml`
<script>
window.config = ${this.renderHtml(JSON.stringify(config))};
</script>
`
Building HTML Programmatically
// Building HTML in parts
const out = [];
out.push(this.renderHtml`<div class="${className}">`);
if(hasHeader) {
out.push(this.renderHtml`<header>${headerContent}</header>`);
}
out.push(this.renderHtml`<main>${mainContent}</main>`);
out.push(this.renderHtml`</div>`);
return this.renderHtml`${out}`;
Integration with Other Services
// Using with renderTag service
const attributes = {
class: 'button',
'data-action': 'submit',
disabled: isDisabled || undefined
};
return this.renderTag('button', {
...attributes,
body: this.renderHtml`${buttonText}`
});
Error-Safe Rendering
// Values that are null, undefined, or false render as empty strings
this.renderHtml`
<div>
${user?.name} <!-- Safe even if user is null -->
${showBadge && this.renderHtml`<span class="badge">New</span>`}
</div>
`
Security Considerations
- Automatic Escaping: All string values are automatically HTML-escaped
- Raw HTML: To include raw HTML, wrap it in an
Html
instance or use nestedrenderHtml
calls - XSS Prevention: The service helps prevent Cross-Site Scripting attacks through automatic escaping
- JSON Safety: When embedding JSON in HTML, always use
this.renderHtml(JSON.stringify(data))
Return Value
The service returns an Html
instance that:
- Can be converted to string with
toString()
- Can be used in HTTP responses with
toResponseArray()
- Is recognized by other
renderHtml
calls as safe HTML content - Integrates seamlessly with the Pinstripe view system
Performance Notes
- Template processing is async-aware and handles promises efficiently
- Array flattening is optimized for nested structures
- Function calls are resolved recursively with proper context
- The service is designed for server-side rendering with client-side availability