Beim Entwerfen einer Vorlage müssen Sie häufig Daten in den Inhalt integrieren: den Namen eines Empfängers aus params, eine Überschrift aus props oder eine Liste von Produkten, die als Tabellenzeilen angezeigt werden. Tembuilder verwendet Handlebars, um diese Werte mit Ihrem HTML/CSS zu verbinden. Mit seiner Syntax können Sie markieren, wo Daten angezeigt werden sollen, und beschreiben, wie Inhalte angezeigt werden sollen.
Schreiben Sie beispielsweise {{ params.recipient }} dorthin, wo der Name des Empfängers hingehört. Wenn Sie eine Vorschau des Dokuments anzeigen oder ein PDF generieren, liest Tembuilder den passenden Wert und ersetzt den Ausdruck durch den tatsächlichen Inhalt. Dadurch können Sie dasselbe Design mit unterschiedlichen Datensätzen wiederverwenden.
Diese Anleitung führt Sie durch das Lesen von Werten aus Parameters und Props, das bedingte Anzeigen von Inhalten, das Wiederholen von Listen und die Verwendung erweiterter Syntax, wenn Ihre Vorlage komplexere Datenstrukturen benötigt.
1. Von der Vorlage zum Dokument
Beginnen Sie mit einem einfachen Beispiel: Sie haben eine Abschnittsstütze heading mit dem Wert Invoice erstellt und einen Parameter recipient mit dem Wert Tembuilder deklariert. Platzieren Sie im HTML des Abschnitts jeden Wert an der Stelle, an der er angezeigt werden soll, indem Sie {{ ... }} verwenden:
<h1>{{ props.heading }}</h1>
<p>{{ params.recipient }}</p>
<h1>Invoice</h1>
<p>Tembuilder</p>
{{ props.heading }} → Invoice{{ params.recipient }} → TembuilderTembuilder
2. Wählen Sie den richtigen Datenpfad
| Pfad | Liest |
|---|---|
{{ params.recipient }} |
Für diesen Lauf bereitgestellte Daten, nachdem Standardwerte angewendet wurden. |
{{ props.heading }} |
Props für den Teil, der kompiliert wird. In einem Abschnitt überschreiben Abschnittswerte gleichnamige Global-Werte. |
{{ global.props.company }} |
Global props explizit, auch wenn ein Abschnitt denselben Namen überschreibt. |
{{ @root.params.recipient }} |
Run-Daten aus einer Schleife oder einem with-Block. |
Verwenden Sie explizite params.-Pfade anstelle bloßer Parameternamen. Stammparameternamen werden aus Kompatibilitätsgründen ebenfalls offengelegt, Namen wie props, params und global werden jedoch vom Plattformkontext belegt.
Jeder Abschnitt, jede Kopf- und Fußzeile wird mit seinem eigenen Kontext zusammengestellt. @root bedeutet das Stammverzeichnis dieser Zusammenstellung, nicht einen anderen Abschnitt. Variants wählt Propsüberschreibungen aus, bevor Ausdrücke ausgeführt werden.
3. Text, Zahlen, Boolesche Werte und fehlende Werte
Das folgende Objekt sind Laufdaten: Geben Sie seine Felder in Run ein, ohne einen äußeren params-Wrapper hinzuzufügen. Deklarieren Sie passende Typen in Parameters → Schema.
{
"recipient": "Tembuilder & Tembuilder",
"quantity": 2,
"balance": 0,
"paid": false,
"totalLabel": "250,000 VND"
}
<p>{{ params.recipient }} · {{ params.quantity }}</p>
<p>{{ params.totalLabel }}</p>
{{#if params.paid}}Paid{{else}}Awaiting payment{{/if}}
Text wird als Text angezeigt, Zahlen zeigen ihren Wert an und das direkte Drucken eines Booleschen Werts erzeugt true oder false. Verwenden Sie eine Bedingung für eine leserfreundliche Beschriftung. Behalten Sie 2 numerisch und false boolesch bei; "2" und "false" sind Zeichenfolgen.
Ein ungelöster Wert gibt normalerweise nichts aus. Dies ist kein Ersatz für die Deklaration erforderlicher Felder oder die Validierung von Laufdaten. Ungültige Syntax oder ein unbekannter Helfer stoppt die Kompilierung.
Handlebars berechnet quantity * price nicht, ruft .toFixed(2) nicht auf und formatiert Datumsangaben/Währungen nicht automatisch. Bereiten Sie vor dem Rendern Summen und formatierte Zeichenfolgen vor. {{ params.quantity + 1 }} und {{ params.total.toFixed(2) }} sind keine unterstützten JavaScript-Ausdrücke.
4. Objekt- und Eigenschaftsnamen
{
"recipient": { "name": "Tembuilder", "address": { "city": "Hanoi" } },
"labels": { "invoice_title": "Invoice", "postal_code": "10000" }
}
<p>{{ params.recipient.name }} · {{ params.recipient.address.city }}</p>
<h2>{{ params.labels.invoice_title }}</h2>
<p>{{ params.labels.postal_code }}</p>
Verwenden Sie Feldnamen wie recipientName oder postal_code. Der Editor ersetzt Leerzeichen, Bindestriche und andere Zeichen außerhalb von Buchstaben, Ziffern und Unterstrichen durch _; Das erste Zeichen muss ein Buchstabe oder ein Unterstrich sein. Für ein vorhandenes importiertes Schema mit Schlüsseln wie postal code kann Handlebars diese mit {{ params.labels.[postal code] }} lesen. Diese Syntax ändert nichts an den Namensregeln des Editors. Um ein Objekt sinnvoll darzustellen, wählen Sie seine Felder aus oder iterieren Sie sie. Das Drucken des gesamten Objekts ist keine JSON-Serialisierung.
5. Bedingungen: if, else, unless
{{#if params.paid}}
<p>Payment received</p>
{{else if params.overdue}}
<p>Payment overdue</p>
{{else}}
<p>Awaiting payment</p>
{{/if}}
{{#unless params.paid}}<p>Please pay before the due date.</p>{{/unless}}
{{#if params.balance includeZero=true}}<p>Balance: {{ params.balance }}</p>{{/if}}
if nimmt den negativen Zweig für false, null, fehlende Werte, eine leere Zeichenfolge, Null und ein leeres Array. includeZero=true bewirkt, dass Null den positiven Zweig einnimmt. Ein leeres Objekt und die Zeichenfolge "false" nehmen den positiven Zweig. unless kehrt den Zustand um. if ändert den aktuellen Kontext nicht.
Auf dieser Plattform gibt es keine integrierten eq-, gt-, and- oder or-Helfer. Berechnen Sie einen booleschen Wert wie overdue in der Eingabe, anstatt {{#if params.balance > 0}} zu schreiben.
6. Arrays: each und leere Zustände
{
"items": [{ "name": "Design", "quantity": 2 }, { "name": "Review", "quantity": 1 }],
"tags": ["Draft", "Internal"]
}
<table>
<thead><tr><th>Item</th><th>Quantity</th></tr></thead>
<tbody>
{{#each params.items}}
<tr><td>{{ this.name }}</td><td>{{ this.quantity }}</td></tr>
{{else}}
<tr><td colspan="2">No items</td></tr>
{{/each}}
</tbody>
</table>
{{#each params.tags}}<span>{{ this }}</span>{{/each}}
this ist das aktuelle Element: ein Objekt für items, eine Zeichenfolge für tags. Mit {{ params.items.[0].name }} ist ein direkter Array-Zugriff möglich. Befolgen Sie für lange Tabellen die Paginierungsanleitung.
{{#each params.items}} {{ this.name }} · {{ this.quantity }}{{else}} No items {{/each}}7. Schleifenmetadaten und Objektiteration
| Ausdruck | Bedeutung innerhalb each |
|---|---|
@index |
Array-Position, beginnend bei Null. |
@first, @last |
Flags für erstes/letztes Array-Element. |
@key |
Eigenschaftsname beim Iterieren eines Objekts. |
{{#each params.tags}}
{{#if @first}}<strong>Tags:</strong>{{/if}}
{{ this }}{{#unless @last}}, {{/unless}}
{{/each}}
{{#each params.recipient}}
<p>{{ @key }}: {{ this }}</p>
{{/each}}
Verwenden Sie @index + 1 nicht zum Erstellen von Zeilennummern. Geben Sie ein rowNumber-Feld an, wenn Sie eine Nummerierung benötigen, die bei eins beginnt.
8. Kontext: with, übergeordnete Pfade und Root
{{#with params.recipient}}
<p>{{ name }}</p>
{{else}}
<p>No recipient</p>
{{/with}}
{{#each params.items}}
<p>{{ this.name }} — {{ ../props.heading }}</p>
<small>{{ @root.global.props.company }}</small>
{{/each}}
with und each ändern den Kontext. ../ kehrt zum übergeordneten Kontext zurück; @root bietet stabilen Zugriff auf das Kompilierungsstammverzeichnis über verschachtelte Schleifen hinweg. Für das Hinzufügen eines if ist kein weiterer ../ erforderlich.
Aliase erleichtern das Verfolgen verschachtelter Listen. Deklarieren Sie hier groups als Array von Objekten mit jeweils einem name- und einem items-Array:
{{#each params.groups as |group groupIndex|}}
<h2>{{ group.name }}</h2>
{{#each group.items as |item itemIndex|}}
<p>{{ groupIndex }}.{{ itemIndex }} — {{ item.name }}</p>
{{/each}}
{{/each}}
9. Dynamische Suche und Unterausdrücke
Verwenden Sie lookup für einen als Daten bereitgestellten Schlüssel. Deklarieren Sie labels als Objekt und selectedKey als Text. für { "labels": { "approved": "Approved" }, "selectedKey": "approved" }:
<p>{{ lookup params.labels params.selectedKey }}</p>
{{#with (lookup params.labels params.selectedKey)}}<strong>{{ this }}</strong>{{/with}}
Klammern verschachteln ein Helferergebnis in einem anderen Helfer. Sie werten kein beliebiges JavaScript aus. Argumente in Anführungszeichen sind Literalzeichenfolgen, während Pfade ohne Anführungszeichen Daten lesen. includeZero=true ist eine benannte Hilfsoption, keine Zuweisung zu Eingabedaten.
10. HTML-Escape- und CSS-Werte
<p>{{ params.recipient }}</p>
Für recipient gleich Tembuilder & Tembuilder enthält die HTML-Quelle Tembuilder & Tembuilder und das Dokument zeigt Tembuilder & Tembuilder an. Behalten Sie doppelte geschweifte Klammern für normale Eingaben bei.
{{{ params.trustedHtml }}} und {{& params.trustedHtml }} fügen HTML ein, ohne zu entkommen. Verwenden Sie sie nur für vertrauenswürdige, bereinigte Markups, die zu Dokumentelementen werden sollen. Escaping ist keine URL- oder CSS-Validierung. Validieren Sie die für href, src oder Stile vorgesehenen Werte.
Im CSS-Editor kann eine kontrollierte Farb-Prop direkt gelesen werden:
h1 { color: {{ props.accent }}; }
Geben Sie accent eine gültige Farbe, z. B. #2563eb. Handlebars bietet Ersatz; Das Ergebnis muss weiterhin gültig sein CSS.
11. Kommentare, Leerzeichen und literale Klammern
{{! Internal note, omitted from output }}
{{!-- A longer note that can include {{ expressions }} --}}
<span>{{ params.recipient ~}}</span>
~ neben einem Trennzeichen schneidet angrenzende Leerzeichen auf dieser Seite ab. Verwenden Sie es vorsichtig um Wörter herum, die ein Trennzeichen benötigen. Handlebars entfernt seine eigenen Kommentare während der Kompilierung. Tembuilder entfernt auch HTML-Kommentare während der Bereinigung, sodass keiner der Typen im endgültigen Dokument HTML verbleibt.
So zeigen Sie einen wörtlichen Ausdruck an, anstatt ihn auszuwerten:
<p>\{{ params.recipient }}</p>
Das Dokument zeigt {{ params.recipient }} an. Rohblöcke ({{{{raw}}}}…{{{{/raw}}}}) erfordern einen registrierten Blockhelfer; Diese Plattform stellt keinen raw-Helfer bereit.
12. Partials und andere erweiterte Funktionen
Ein Inline-Teil kann Markup innerhalb einer kompilierten Quelle wiederverwenden:
{{#*inline "recipientCard"}}
<p>{{ name }}</p>
{{/inline}}
{{> recipientCard params.recipient}}
Es wird nicht automatisch für Abschnittsdateien, Kopf- oder Fußzeilen freigegeben. {{> sharedCard}} benötigt eine Definition; Tembuilder stellt keine Registrierung für benutzerdefinierte globale Partials oder benutzerdefinierte JavaScript-Helfer bereit.
Handlebars unterstützt auch Teilparameter, dynamische Teilauswahl, Teilblöcke und benutzerdefinierte Blockhelfer. Hierbei handelt es sich um Sprachfunktionen, nicht um ein Versprechen von Plattformregistrierungsfunktionen. Fügen Sie keine registerHelper-, registerPartial- oder Skript-Tags in die Vorlage HTML ein, in der Erwartung, dass sie die Kompilierung konfigurieren.
Der integrierte log-Helfer schreibt in das Protokoll der Ausführungsumgebung und nicht in PDF. Bevorzugen Sie Vorschau und Run, um die Ausgabe zu überprüfen. Vermeiden Sie die Protokollierung vertraulicher Laufdaten. Dekoratoren und Zugriff auf Prototypen/Methoden sind für die Dokumentenerstellung nicht erforderlich: Verwenden Sie einfache JSON-Werte und die dokumentierten Hilfsprogramme.
13. Vollständiges Abschnittsbeispiel
Erstellen Sie die Abschnittsstütze heading = "Invoice" und die Global-Stütze company = "Tembuilder". Deklarieren Sie recipient (Objekt mit name: Text), items (Array von Objekten mit name: Text und quantity: Zahl), paid (Boolescher Wert) und totalLabel (Text). Run mit:
{
"recipient": { "name": "Tembuilder" },
"items": [{ "name": "Design", "quantity": 2 }],
"paid": false,
"totalLabel": "250,000 VND"
}
In den Abschnitt HTML einfügen:
<h1>{{ props.heading }}</h1>
<p>{{ global.props.company }} → {{ params.recipient.name }}</p>
<ul>
{{#each params.items}}
<li>{{ this.name }} × {{ this.quantity }}</li>
{{else}}
<li>No items</li>
{{/each}}
</ul>
<p>Total: {{ params.totalLabel }}</p>
<p>{{#if params.paid}}Paid{{else}}Awaiting payment{{/if}}</p>
Erwarteter Inhalt: Rechnung, Tembuilder → Tembuilder, Design × 2, Gesamt: 250.000 VND, Zahlung ausstehend. Versuchen Sie es mit einem leeren items-Array und paid: true, um beide alternativen Zweige in Preview/Run zu überprüfen.
14. Regeln zur Fehlerbehebung und KI-Erstellung
| Symptom | Überprüfen |
|---|---|
| Leerer Wert | Feldschreibweise, deklarierter Typ, Nutzlast ausführen, aktive Variante und aktueller Kontext. |
| Falscher Wert innerhalb einer Schleife | Verwenden Sie this, einen Alias, ../ oder @root, um den gewünschten Kontext auszuwählen. |
| Null ausgeblendet | Verwenden Sie includeZero=true, wobei Null ein gültiger angezeigter Wert ist. |
| Unerwarteter positiver Zustand | Suchen Sie nach einer Zeichenfolge "false" anstelle des booleschen Werts false. |
| Kompilierungsfehler | Passen Sie die Eröffnungs-/Schließnamen jedes Blocks an; Entfernen Sie JavaScript-Operatoren und nicht verfügbare Helfer/Teilfunktionen. |
[object Object] |
Wählen Sie Objektfelder aus oder iterieren Sie sie, anstatt das gesamte Objekt zu drucken. |
Für KI-Autoren: Behalten Sie deklarierte Feldnamen und -typen bei, verwenden Sie explizite Namespaces, berechnen Sie die Geschäftslogik vor dem Rendern, stellen Sie leere Zustände bereit, behalten Sie das Escapezeichen für gewöhnliche Werte bei und überprüfen Sie Beispiele sowohl anhand aufgefüllter als auch an leeren Daten. Ein fehlender Wert ist kein Beweis für eine erfolgreiche Bindung. Siehe häufige Fehler.
15. Offizielle Handlebars-Referenzen
Verwenden Sie den offiziellen Handlebars-Leitfaden für die vollständige Sprachdokumentation. Das oben beschriebene Plattformverhalten hat Vorrang, wenn ein Upstream-Beispiel eine hostseitige Registrierung oder Laufzeitkonfiguration erfordert.