Lors de la conception d’un modèle, vous devez souvent introduire des données dans son contenu : le nom d’un destinataire de params, un en-tête de props ou une liste de produits affichée sous forme de lignes de tableau. Tembuilder utilise Handlebars pour connecter ces valeurs à votre HTML/CSS. Sa syntaxe vous permet de marquer où les données doivent apparaître et de décrire comment le contenu doit être affiché.
Par exemple, écrivez {{ params.recipient }} à la place du nom du destinataire. Lorsque vous prévisualisez le document ou générez un PDF, Tembuilder lit la valeur correspondante et remplace l’expression par le contenu réel. Cela vous permet de réutiliser la même conception avec différents ensembles de données.
Ce guide vous guide à travers la lecture des valeurs de Parameters et Props, en affichant le contenu de manière conditionnelle, en répétant des listes et en utilisant une syntaxe avancée lorsque votre modèle nécessite des structures de données plus complexes.
1. Du modèle au document
Commencez par un exemple simple : vous avez créé une section prop heading avec la valeur Invoice et déclaré un paramètre recipient avec la valeur Tembuilder. Dans le HTML de la section, placez chaque valeur à l’endroit où vous souhaitez qu’elle apparaisse à l’aide de {{ ... }} :
<h1>{{ props.heading }}</h1>
<p>{{ params.recipient }}</p>
<h1>Invoice</h1>
<p>Tembuilder</p>
{{ props.heading }} → Invoice{{ params.recipient }} → TembuilderTembuilder
2. Choisissez le bon chemin de données
| Chemin | Lectures |
|---|---|
{{ params.recipient }} |
Données fournies pour cette exécution, une fois les valeurs par défaut appliquées. |
{{ props.heading }} |
Props pour la pièce en cours de compilation. Dans une section, les valeurs de section remplacent les valeurs Global portant le même nom. |
{{ global.props.company }} |
Global props explicitement, même lorsqu’une section remplace le même nom. |
{{ @root.params.recipient }} |
Données Run provenant de l’intérieur d’une boucle ou d’un bloc with. |
Utilisez des chemins params. explicites au lieu de noms de paramètres nus. Les noms des paramètres racine sont également exposés pour des raisons de compatibilité, mais les noms tels que props, params et global sont occupés par le contexte de la plateforme.
Chaque section, en-tête et pied de page est compilé avec son propre contexte. @root signifie la racine de cette compilation, pas une autre section. Variants sélectionne les remplacements de prop avant l’exécution des expressions.
3. Texte, nombres, booléens et valeurs manquantes
L’objet suivant est run data : saisissez ses champs dans Run sans ajouter de wrapper params externe. Déclarez les types correspondants dans 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}}
Le texte s’affiche sous forme de texte, les nombres affichent leur valeur et l’impression directe d’un booléen produit true ou false. Utilisez une condition pour une étiquette conviviale. Conservez 2 numérique et false booléen ; "2" et "false" sont des chaînes.
Une valeur non résolue n’imprime normalement rien. Cela ne remplace pas la déclaration des champs obligatoires ou la validation des données d’exécution. Une syntaxe invalide ou un assistant inconnu arrête la compilation.
Handlebars ne calcule pas quantity * price, n’appelle pas .toFixed(2) et ne formate pas automatiquement les dates/devises. Préparez les totaux et les chaînes formatées avant le rendu. {{ params.quantity + 1 }} et {{ params.total.toFixed(2) }} ne sont pas des expressions JavaScript prises en charge.
4. Objets et noms de propriétés
{
"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>
Utilisez des noms de champs tels que recipientName ou postal_code. L’éditeur remplace les espaces, les tirets et autres caractères en dehors des lettres, des chiffres et des traits de soulignement par _ ; le premier caractère doit être une lettre ou un trait de soulignement. Pour un schéma importé existant avec des clés telles que postal code, Handlebars peut les lire à l’aide de {{ params.labels.[postal code] }}. Cette syntaxe ne modifie pas les règles de dénomination de l’éditeur. Pour restituer un objet de manière significative, sélectionnez ses champs ou itérez-les ; l’impression de l’objet entier n’est pas une sérialisation JSON.
5. Conditions : 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 prend la branche négative pour false, null, les valeurs manquantes, une chaîne vide, zéro et un tableau vide. includeZero=true fait prendre à zéro la branche positive. Un objet vide et la chaîne "false" prennent la branche positive. unless inverse la condition. if ne change pas le contexte actuel.
Il n’y a pas d’assistants eq, gt, and ou or intégrés dans cette plate-forme. Calculez un booléen tel que overdue dans l’entrée au lieu d’écrire {{#if params.balance > 0}}.
6. Tableaux : each et états vides
{
"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 est l’élément actuel : un objet pour items, une chaîne pour tags. L’accès direct à la baie est possible avec {{ params.items.[0].name }}. Pour les tableaux longs, suivez guide de pagination.
{{#each params.items}} {{ this.name }} · {{ this.quantity }}{{else}} No items {{/each}}7. Métadonnées de boucle et itération d’objet
| Expression | Signification à l’intérieur de each |
|---|---|
@index |
Position du tableau, en commençant à zéro. |
@first, @last |
Indicateurs du premier/dernier élément du tableau. |
@key |
Nom de la propriété lors de l’itération d’un objet. |
{{#each params.tags}}
{{#if @first}}<strong>Tags:</strong>{{/if}}
{{ this }}{{#unless @last}}, {{/unless}}
{{/each}}
{{#each params.recipient}}
<p>{{ @key }}: {{ this }}</p>
{{/each}}
N’utilisez pas @index + 1 pour créer des numéros de ligne. Fournissez un champ rowNumber si vous avez besoin d’une numérotation commençant par un.
8. Contexte : with, chemins parents et racine
{{#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 et each changent de contexte. ../ renvoie au contexte parent ; @root fournit un accès stable à la racine de compilation à travers des boucles imbriquées. L’ajout d’un if ne nécessite pas un autre ../.
Les alias facilitent le suivi des listes imbriquées. Ici, déclarez groups comme un tableau d’objets, chacun avec un tableau name et un tableau items :
{{#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. Recherche dynamique et sous-expressions
Utilisez lookup pour une clé fournie en données. Déclarez labels comme objet et selectedKey comme texte ; pour { "labels": { "approved": "Approved" }, "selectedKey": "approved" } :
<p>{{ lookup params.labels params.selectedKey }}</p>
{{#with (lookup params.labels params.selectedKey)}}<strong>{{ this }}</strong>{{/with}}
Les parenthèses imbriquent un résultat d’assistance dans un autre assistant. Ils n’évaluent pas les JavaScript arbitraires. Les arguments entre guillemets sont des chaînes littérales, tandis que les chemins sans guillemets lisent les données. includeZero=true est une option d’assistance nommée, pas une affectation aux données d’entrée.
10. Échappement HTML et valeurs CSS
<p>{{ params.recipient }}</p>
Pour recipient égal à Tembuilder & Tembuilder, la source HTML contient Tembuilder & Tembuilder et le document affiche Tembuilder & Tembuilder. Conservez des accolades doubles pour une saisie ordinaire.
{{{ params.trustedHtml }}} et {{& params.trustedHtml }} insèrent HTML sans s’échapper. Utilisez-les uniquement pour le balisage fiable et aseptisé que vous avez l’intention de devenir des éléments de document. L’échappement n’est pas une validation d’URL ou de CSS. Validez les valeurs destinées à href, src ou aux styles.
Dans l’éditeur CSS, un accessoire Color contrôlé peut être lu directement :
h1 { color: {{ props.accent }}; }
Donnez à accent une couleur valide telle que #2563eb. Handlebars fournit une substitution ; le résultat doit toujours être valide CSS.
11. Commentaires, espaces et accolades littérales
{{! Internal note, omitted from output }}
{{!-- A longer note that can include {{ expressions }} --}}
<span>{{ params.recipient ~}}</span>
~ à côté d’un délimiteur coupe les espaces adjacents de ce côté. Utilisez-le avec précaution autour des mots qui nécessitent un espace de séparation. Handlebars supprime ses propres commentaires lors de la compilation. Tembuilder supprime également les commentaires HTML lors de la désinfection, de sorte qu’aucun des deux types ne reste dans le document final HTML.
Pour afficher une expression littérale plutôt que de l’évaluer :
<p>\{{ params.recipient }}</p>
Le document affiche {{ params.recipient }}. Les blocs bruts ({{{{raw}}}}…{{{{/raw}}}}) nécessitent un assistant de bloc enregistré ; cette plateforme ne fournit pas d’assistant raw.
12. Partiels et autres fonctionnalités avancées
Un partiel en ligne peut réutiliser le balisage dans une source compilée :
{{#*inline "recipientCard"}}
<p>{{ name }}</p>
{{/inline}}
{{> recipientCard params.recipient}}
Il n’est pas partagé automatiquement entre les fichiers de section, les en-têtes ou les pieds de page. {{> sharedCard}} a besoin d’une définition ; Tembuilder n’expose pas de registre pour les partiels globaux définis par l’utilisateur ou les assistants JavaScript personnalisés.
Handlebars prend également en charge les paramètres partiels, la sélection partielle dynamique, les blocs partiels et les assistants de bloc personnalisés. Il s’agit de capacités linguistiques et non d’une promesse de fonctionnalités d’enregistrement sur la plateforme. Ne collez pas registerHelper, registerPartial ou les balises de script dans le modèle HTML en attendant qu’ils configurent la compilation.
L’assistant log intégré écrit dans le journal de l’environnement d’exécution plutôt que dans le PDF. Préférez Aperçu et Run pour inspecter la sortie ; évitez de consigner des données d’exécution sensibles. Les décorateurs et l’accès aux prototypes/méthodes ne sont pas nécessaires pour la création de documents : utilisez des valeurs JSON simples et les assistants documentés.
13. Exemple de section complète
Créez les Props de section heading = "Invoice" et les Props Global company = "Tembuilder". Déclarez recipient (Objet avec name : Texte), items (Tableau d’objets avec name : Texte et quantity : Nombre), paid (Booléen) et totalLabel (Texte). Run avec :
{
"recipient": { "name": "Tembuilder" },
"items": [{ "name": "Design", "quantity": 2 }],
"paid": false,
"totalLabel": "250,000 VND"
}
Coller dans la section HTML :
<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>
Contenu attendu : Facture, Tembuilder → Tembuilder, Design × 2, Total : 250 000 VND, En attente de paiement. Essayez un tableau items vide et un paid: true pour vérifier les deux branches alternatives dans Preview/Run.
14. Dépannage et règles de création d’IA
| Symptôme | Vérifier |
|---|---|
| Valeur vide | Orthographe du champ, type déclaré, charge utile d’exécution, variante active et contexte actuel. |
| Mauvaise valeur dans une boucle | Utilisez this, un alias, ../ ou @root pour sélectionner le contexte souhaité. |
| Zéro caché | Utilisez includeZero=true où zéro est une valeur affichée valide. |
| Condition positive inattendue | Recherchez une chaîne "false" au lieu de la booléenne false. |
| Erreur de compilation | Faites correspondre les noms d’ouverture/fermeture de chaque bloc ; supprimez les opérateurs JavaScript et les assistants/partiels indisponibles. |
[object Object] |
Sélectionnez les champs de l’objet ou itérez-les au lieu d’imprimer l’objet entier. |
Pour les auteurs d’IA : conservez les noms et les types de champs déclarés, utilisez des espaces de noms explicites, calculez la logique métier avant le rendu, fournissez des états vides, conservez les valeurs ordinaires échappées et vérifiez les exemples par rapport aux données renseignées et vides. Une valeur manquante ne prouve pas une liaison réussie. Voir erreurs courantes.
15. Références officielles Handlebars
Utilisez le guide officiel Handlebars pour la documentation linguistique complète. Le comportement de la plateforme décrit ci-dessus est prioritaire lorsqu’un exemple en amont nécessite un enregistrement côté hôte ou une configuration d’exécution.