Datos y variantes
Docs/Datos y variantes

Referencia de sintaxis de Handlebars

Incorpore parámetros y props a su plantilla con Handlebars, desde mostrar texto hasta crear tablas y contenido condicional.

10 minutos de lectura15 secciones
En esta página

Al diseñar una plantilla, a menudo es necesario incluir datos en su contenido: el nombre de un destinatario de params, un encabezado de props o una lista de productos mostrados como filas de una tabla. Tembuilder usa Handlebars para conectar estos valores a su HTML/CSS. Su sintaxis le permite marcar dónde deben aparecer los datos y describir cómo se debe mostrar el contenido.

Por ejemplo, escribe {{ params.recipient }} donde pertenece el nombre del destinatario. Cuando obtiene una vista previa del documento o genera un PDF, Tembuilder lee el valor coincidente y reemplaza la expresión con el contenido real. Esto le permite reutilizar el mismo diseño con diferentes conjuntos de datos.

Esta guía lo guía a través de la lectura de valores de Parameters y Props, mostrando contenido condicionalmente, repitiendo listas y usando sintaxis avanzada cuando su plantilla necesita estructuras de datos más complejas.

1. De la plantilla al documento

Comience con un ejemplo simple: ha creado un accesorio de sección heading con el valor Invoice y ha declarado un parámetro recipient con el valor Tembuilder. En el HTML de la sección, coloca cada valor donde quieras que aparezca usando {{ ... }}:

<h1>{{ props.heading }}</h1>
<p>{{ params.recipient }}</p>
<h1>Invoice</h1>
<p>Tembuilder</p>
{{ props.heading }} → Invoice{{ params.recipient }} → Tembuilder
→
TembuilderFactura

Tembuilder

Las expresiones se reemplazan antes de la paginación PDF.

2. Elija la ruta de datos correcta

Camino Lecturas
{{ params.recipient }} Datos proporcionados para esta ejecución, después de aplicar los valores predeterminados.
{{ props.heading }} Props para la parte que se está compilando. En una sección, los valores de la sección anulan los valores Global con el mismo nombre.
{{ global.props.company }} Global props explícitamente, incluso cuando una sección anula el mismo nombre.
{{ @root.params.recipient }} Datos Run desde dentro de un bucle o bloque with.

Utilice rutas params. explícitas en lugar de nombres de parámetros simples. Los nombres de los parámetros raíz también se exponen por motivos de compatibilidad, pero nombres como props, params y global están ocupados por el contexto de la plataforma.

Cada sección, encabezado y pie de página se compila con su propio contexto. @root significa la raíz de esa compilación, no otra sección. Variants selecciona anulaciones de Props antes de ejecutar las expresiones.

3. Texto, números, valores booleanos y valores faltantes

El siguiente objeto es ejecutar datos: ingrese sus campos en Run sin agregar un contenedor externo params. Declare tipos coincidentes en 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}}

El texto se muestra como texto, los números muestran su valor y la impresión directa de un booleano produce true o false. Utilice una condición para una etiqueta fácil de leer. Mantenga 2 numérico y false booleano; "2" y "false" son cadenas.

Un valor no resuelto normalmente no imprime nada. Esto no sustituye a declarar campos obligatorios o validar datos de ejecución. La sintaxis no es válida o un asistente desconocido detiene la compilación.

Handlebars no calcula quantity * price, no llama a .toFixed(2) ni formatea fechas/monedas automáticamente. Prepare totales y cadenas formateadas antes de renderizar. {{ params.quantity + 1 }} y {{ params.total.toFixed(2) }} no son expresiones compatibles con JavaScript.

4. Objetos y nombres de propiedades

{
  "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>

Utilice nombres de campo como recipientName o postal_code. El editor reemplaza espacios, guiones y otros caracteres fuera de letras, dígitos y guiones bajos con _; el primer carácter debe ser una letra o un guión bajo. Para un esquema importado existente con claves como postal code, Handlebars puede leerlas usando {{ params.labels.[postal code] }}. Esa sintaxis no cambia las reglas de nomenclatura del editor. Para representar un objeto de manera significativa, seleccione sus campos o repítalos; imprimir todo el objeto no es una serialización JSON.

5. Condiciones: 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 toma la rama negativa para false, null, valores faltantes, una cadena vacía, cero y una matriz vacía. includeZero=true hace que el cero tome la rama positiva. Un objeto vacío y la cadena "false" toman la rama positiva. unless invierte la condición. if no cambia el contexto actual.

No hay asistentes eq, gt, and o or integrados en esta plataforma. Calcule un booleano como overdue en la entrada en lugar de escribir {{#if params.balance > 0}}.

6. Arrays: each y estados vacíos

{
  "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 es el elemento actual: un objeto para items, una cadena para tags. El acceso directo a la matriz es posible con {{ params.items.[0].name }}. Para tablas largas, siga la guía de paginación.

{{#each params.items}} {{ this.name }} · {{ this.quantity }}{{else}} No items {{/each}}
ArtículoCantidad
Diseño2
Revisión1
Un artículo → una fila. Una lista vacía → la rama else.

7. Metadatos de bucle e iteración de objetos

Expresión Significado dentro de each
@index Posición del array, comenzando en cero.
@first, @last Banderas del primer/último elemento de la matriz.
@key Nombre de propiedad al iterar un objeto.
{{#each params.tags}}
  {{#if @first}}<strong>Tags:</strong>{{/if}}
  {{ this }}{{#unless @last}}, {{/unless}}
{{/each}}
{{#each params.recipient}}
  <p>{{ @key }}: {{ this }}</p>
{{/each}}

No utilice @index + 1 para crear números de fila. Proporcione un campo rowNumber si necesita una numeración que comience en uno.

8. Contexto: with, rutas padre y raíz

{{#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 y each cambian de contexto. ../ vuelve al contexto principal; @root proporciona acceso estable a la raíz de compilación a través de bucles anidados. Agregar un if no requiere otro ../.

Los alias hacen que las listas anidadas sean más fáciles de seguir. Aquí, declara groups como una matriz de objetos, cada uno con una matriz name y una matriz 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. Búsqueda dinámica y subexpresiones

Utilice lookup para una clave proporcionada como datos. Declare labels como objeto y selectedKey como Texto; Para { "labels": { "approved": "Approved" }, "selectedKey": "approved" }:

<p>{{ lookup params.labels params.selectedKey }}</p>
{{#with (lookup params.labels params.selectedKey)}}<strong>{{ this }}</strong>{{/with}}

Los paréntesis anidan un resultado auxiliar dentro de otro auxiliar. No evalúan JavaScript arbitrario. Los argumentos entre comillas son cadenas literales, mientras que las rutas sin comillas leen datos. includeZero=true es una opción de ayuda con nombre, no una asignación para ingresar datos.

10. Escape HTML y valores CSS

<p>{{ params.recipient }}</p>

Para recipient igual a Tembuilder & Tembuilder, la fuente HTML contiene Tembuilder &amp; Tembuilder y el documento muestra Tembuilder & Tembuilder. Mantenga llaves dobles para la entrada ordinaria.

{{{ params.trustedHtml }}} y {{& params.trustedHtml }} insertan HTML sin escapar. Úselos únicamente para marcas confiables y desinfectadas que desee convertir en elementos del documento. Escapar no es una validación de URL o CSS. Valide los valores destinados a href, src o estilos.

En el editor CSS, un accesorio de color controlado se puede leer directamente:

h1 { color: {{ props.accent }}; }

Asigne a accent un color válido como #2563eb. Handlebars proporciona sustitución; el resultado aún debe ser válido CSS.

11. Comentarios, espacios en blanco y llaves literales

{{! Internal note, omitted from output }}
{{!-- A longer note that can include {{ expressions }} --}}
<span>{{ params.recipient ~}}</span>

~ junto a un delimitador recorta los espacios en blanco adyacentes en ese lado. Úselo con cuidado alrededor de palabras que necesitan un espacio de separación. Handlebars elimina sus propios comentarios durante la compilación. Tembuilder también elimina los comentarios de HTML durante la desinfección, por lo que ninguno de los tipos permanece en el documento final HTML.

Para mostrar una expresión literal en lugar de evaluarla:

<p>\{{ params.recipient }}</p>

El documento muestra {{ params.recipient }}. Los bloques sin formato ({{{{raw}}}}…{{{{/raw}}}}) requieren un asistente de bloque registrado; Esta plataforma no proporciona un asistente raw.

12. Parciales y otras funciones avanzadas

Un parcial en línea puede reutilizar el marcado dentro de una fuente compilada:

{{#*inline "recipientCard"}}
  <p>{{ name }}</p>
{{/inline}}
{{> recipientCard params.recipient}}

No se comparte automáticamente entre archivos de sección, encabezados o pies de página. {{> sharedCard}} necesita una definición; Tembuilder no expone un registro para parciales globales definidos por el usuario ni ayudantes personalizados de JavaScript.

Handlebars también admite parámetros parciales, selección parcial dinámica, bloques parciales y ayudas de bloques personalizados. Estas son capacidades de idioma, no una promesa de funciones de registro en la plataforma. No pegue etiquetas registerHelper, registerPartial o script en la plantilla HTML esperando que configuren la compilación.

El asistente integrado log escribe en el registro del entorno de ejecución en lugar de en PDF. Prefiera Vista previa y Run para inspeccionar la salida; Evite registrar datos de ejecución confidenciales. No se necesitan decoradores ni acceso a prototipos/métodos para la creación de documentos: utilice valores JSON simples y los ayudantes documentados.

13. Ejemplo de sección completa

Cree el accesorio de sección heading = "Invoice" y el accesorio Global company = "Tembuilder". Declare recipient (Objeto con name: Texto), items (Matriz de objetos con name: Texto y quantity: Número), paid (Booleano) y totalLabel (Texto). Run con:

{
  "recipient": { "name": "Tembuilder" },
  "items": [{ "name": "Design", "quantity": 2 }],
  "paid": false,
  "totalLabel": "250,000 VND"
}

Pegar en la sección 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>

Contenido esperado: Factura, Tembuilder → Tembuilder, Diseño × 2, Total: 250 000 VND, Pendiente de pago. Pruebe con una matriz items vacía y paid: true para verificar ambas ramas alternativas en Vista previa/Run.

14. Resolución de problemas y reglas de creación de IA

Síntoma Verificar
Valor vacío Ortografía del campo, tipo declarado, carga útil de ejecución, variante activa y contexto actual.
Valor incorrecto dentro de un bucle Utilice this, un alias, ../ o @root para seleccionar el contexto deseado.
Cero oculto Utilice includeZero=true donde cero es un valor mostrado válido.
Condición positiva inesperada Busque una cadena "false" en lugar del booleano false.
Error de compilación Haga coincidir los nombres de apertura/cierre de cada bloque; elimine los operadores JavaScript y los ayudantes/parciales no disponibles.
[object Object] Seleccione campos de objetos o repítalos en lugar de imprimir el objeto completo.

Para autores de IA: conserve los nombres y tipos de campos declarados, utilice espacios de nombres explícitos, calcule la lógica empresarial antes de renderizar, proporcione estados vacíos, mantenga los valores ordinarios escapados y verifique ejemplos con datos tanto completos como vacíos. Un valor faltante no demuestra una vinculación exitosa. Consulte errores comunes.

15. Referencias oficiales de Handlebars

Utilice la guía oficial Handlebars para obtener la documentación completa en el idioma. El comportamiento de la plataforma descrito anteriormente tiene prioridad cuando un ejemplo ascendente requiere registro del lado del host o configuración del tiempo de ejecución.

Buscar documentación