How do I generate a template?
Every component inherits generateTemplate(): Nutin.Template (a string or an html result) from BaseComponent. render() calls it, sanitizes the result and inserts the resulting nodes into the component's element.
You can override it when a template needs more than a single expression.
When to use it
- The markup branches or is assembled conditionally
- The template needs instance state rather than only the
configargument atemplateFnreceives.
In a Component
Don't pass a templateFn to super().
- Override
generateTemplate()and read fromthis.configinstead:
// avatar.component.ts
import { Component, html, raw } from '../../../core/index.js';
interface AvatarConfig {
alt: string;
src?: string;
initials?: string;
shape?: 'circle' | 'square';
}
export class AvatarComponent extends Component<HTMLDivElement, AvatarConfig> {
constructor(mountTarget: HTMLElement, config: AvatarConfig, props?: Nutin.ComponentProps) {
super({ mountTarget, config, normalizeKeys: ['src', 'initials', 'shape'], props });
}
protected override onBeforeRender(): void {
super.onBeforeRender();
this.element.classList.add('app-avatar', `avatar--${this.config.shape || 'circle'}`);
}
protected override generateTemplate(): Nutin.Template {
const { src, alt, initials } = this.config;
if (src) {
return html`<img class="avatar__img" src="${src}" alt="${alt}" loading="lazy">`;
}
return html`<span class="avatar__initials" aria-hidden="true">${initials}</span>`;
}
}
- Attributes that depend on optional flags can be nested
htmlfragments.falserenders nothing, andraw()marks a fixed attribute as markup:
protected override generateTemplate(): Nutin.Template {
const { id, name, checked, disabled } = this.config;
return html`<input
type="checkbox"
${id && html`id="${id}"`}
${name && html`name="${name}"`}
${checked && raw('checked')}
${disabled && raw('disabled')}
>`;
}
Notes
- The template you return still goes through the full pipeline: sanitized according to
trustLevel, then children are mounted,data-i18n/data-pipeare hydrated, emptydata-optionalelements are removed anddata-eventlisteners are bound. - Return an
htmltemplate so interpolated data is escaped. A plain template literal escapes nothing, see How do I control HTML sanitization?. - Work on the rendered children (e.g.
querySelector) belongs inonAfterRender(). In aComponent, callsuper.onBeforeRender()/super.onAfterRender().