oneVcard Template-Engine
An ausgewählten Stellen steht dir die oneVcard Template-Engine zur Verfügung. Dadurch kannst du deinen Inhalt mit dynamischen Daten aufbereiten.
Einfache Platzhalter
Ein Feldname in doppelten geschwungenen Klammern wird durch den zugehörigen Wert ersetzt.
{{placeholder}}Beispiel:
Daten:
{ "firstName": "Max", "lastName": "Mustermann" }Vorlage:
Hallo {{firstName}} {{lastName}}!Ergebnis:
Hallo Max Mustermann!Fehlende Werte
Wenn ein Platzhalter keinen Wert in den Daten findet, wird er durch einen leeren String ersetzt.
Hallo {{name}}! → Hallo !Pfadauflösung
Platzhalter können auf verschachtelte Felder in Objekten und Arrays zugreifen.
Verschachtelte Objekte
Verwende einen Punkt (.) als Trennzeichen:
{{user.address.city}}Daten:
{ "user": { "address": { "city": "München" } }}Ergebnis: München
Arrays per Index
Arrays werden per nullbasiertem Index angesprochen:
{{contacts[0].name}}{{contacts[1].email}}Daten:
{ "contacts": [ { "name": "Anna", "email": "anna@example.com" }, { "name": "Bob", "email": "bob@example.com" } ]}Ergebnis: Anna / bob@example.com
Array-Filter
Du kannst ein Array nach einem bestimmten Feld filtern und dann auf das Ergebnis zugreifen:
{{contacts(type=billing_address)[0].name}}Das filtert das contacts-Array nach allen Einträgen, bei denen type === "billing_address" ist und liefert den ersten Treffer.
Optionale Blöcke
Optionale Blöcke werden in doppelten eckigen Klammern geschrieben: [[ ... ]]
[[Straße: {{address.street}}]][[PLZ: {{address.zipCode}}]]Daten:
{ "address": { "street": "Musterstraße 1" } }Ergebnis:
Straße: Musterstraße 1Der PLZ-Block fehlt komplett, weil address.zipCode nicht vorhanden ist.
Mehrere Platzhalter in einem Block
Alle Platzhalter im Block müssen vorhanden sein, damit der Block ausgegeben wird:
[[{{firstName}} {{lastName}}]]Nur wenn beide Felder vorhanden sind, erscheint der Block.
Bedingungen
Mit Bedingungen kannst du Inhalte abhängig von den Daten ein- oder ausblenden.
Grundstruktur
{#if condition} Content{/if}{#if condition} Content{:else} Fallback{/if}{#if condition1} Content 1{:else if condition2} Content 2{:else} Fallback{/if}Wahrheitswerte (Truthy/Falsy)
Wenn du einfach auf das Vorhandensein oder den Wahrheitswert eines Feldes prüfst:
| Wert | Ergebnis |
|---|---|
true, "true", nicht-leerer String | wahr |
| nicht-leeres Array | wahr |
false, "false", 0, "" | falsch |
fehlendes / null / undefined | falsch |
{#if user.active}Konto ist aktiv{:else}Konto gesperrt{/if}Vergleichsoperatoren
| Operator | Bedeutung |
|---|---|
== | gleich |
!= | ungleich |
> | größer als |
< | kleiner als |
>= | größer oder gleich |
<= | kleiner oder gleich |
{#if user.age >= 18}Volljährig{:else}Minderjährig{/if}{#if user.role == 'admin'}Administratorzugriff{/if}{#if status != 'gesperrt'}Zugang erlaubt{/if}Strings in Bedingungen werden in einfache oder doppelte Anführungszeichen gesetzt:
{#if country == "DE"}Willkommen in Deutschland{/if}{#if country == 'AT'}Willkommen in Österreich{/if}Logische Operatoren
Bedingungen können mit && (UND) und || (ODER) verknüpft werden:
{#if active && age >= 18}Zugriff erlaubt{/if}{#if role == 'admin' || role == 'manager'}Verwaltung{/if}{#if a || b || c}Mindestens eines trifft zu{/if}Klammerung
Verwende Klammern, um die Auswertungsreihenfolge festzulegen:
{#if (role == 'admin' || role == 'editor') && active}Aktiver Redakteur{/if}{#if age >= 18 && (member || promo)}Rabatt verfügbar{/if}Block-Funktionen
Block-Funktionen umschließen einen Inhalt und transformieren oder steuern dessen Ausgabe.
{{#function attribute="value"}} Inhalt{{/function}}join
Verbindet mehrere optionale Blöcke mit einem Trennzeichen. Blöcke, deren Platzhalter keinen Wert haben, werden automatisch übersprungen.
Attribute:
| Attribut | Beschreibung | Standard |
|---|---|---|
delimiter | Trennzeichen zwischen den Blöcken | "" |
prefix | Text vor dem Ergebnis | "" |
suffix | Text nach dem Ergebnis | "" |
Beispiel - Adresszeile:
{{#join delimiter=", "}} [[{{street}}]] [[{{zipCode}} {{city}}]] [[{{country}}]]{{/join}}Daten:
{ "street": "Musterstraße 1", "city": "München" }Ergebnis: Musterstraße 1, München
zipCode und city fehlen. Ihre Blöcke werden übersprungen, keine doppelten Kommas.
Beispiel - mit Prefix und Suffix:
{{#join delimiter=" · " prefix="[" suffix="]"}} [[{{tag1}}]][[{{tag2}}]][[{{tag3}}]]{{/join}}Daten:
{ "tag1": "Rechnung", "tag3": "Dringend" }Ergebnis: [Rechnung · Dringend]
Zeilenumbruch als Trennzeichen:
Verwende \n für einen Zeilenumbruch:
{{#join delimiter="\n"}}[[{{line1}}]][[{{line2}}]][[{{line3}}]]{{/join}}uppercase
Wandelt den gesamten Inhalt in Großbuchstaben um.
{{#uppercase}}{{salutation}} {{lastName}}{{/uppercase}}Daten:
{ "salutation": "Herr", "lastName": "Müller" }Ergebnis: HERR MÜLLER
format
Formatiert einen Wert nach einem bestimmten Stil.
Attribute:
| Attribut | Beschreibung |
|---|---|
style | Formatierungsstil: "phoneNumber" oder "date" |
Telefonnummer formatieren (style="phoneNumber")
Formatiert eine Telefonnummer in das internationale Format.
| Attribut | Beschreibung | Standard |
|---|---|---|
country | Ländercode (ISO 3166-1) für Nummern ohne Vorwahl | keiner |
{{#format style="phoneNumber"}}{{phoneNumber}}{{/format}}Nummern mit internationalem Prefix (+49, +1, +44, …) werden automatisch korrekt dem jeweiligen Land zugeordnet, kein country-Attribut nötig:
+491782367141 → +49 178 2367141+12025550123 → +1 202 555 0123+447911123456 → +44 7911 123456Nummern ohne Prefix benötigen das country-Attribut:
{{#format style="phoneNumber" country="DE"}}{{phoneNumber}}{{/format}}
089123456 → +49 89 123456Kann die Nummer nicht geparst werden, wird der ursprüngliche Wert unverändert ausgegeben.
Datum formatieren (style="date")
Formatiert ein Datum nach einem Pattern oder einer Sprache.
| Attribut | Beschreibung | Standard |
|---|---|---|
pattern | Ausgabeformat (Token-Pattern, siehe unten) | Locale-abhängig |
locale | Sprach-/Regionsformat für die Ausgabe ohne pattern | "de-DE" |
inputFormat | Eingabeformat, wenn der Wert kein ISO-Datum ist (Token-Pattern) | automatisch |
Pattern-Tokens
| Token | Beschreibung | Beispiel |
|---|---|---|
yyyy | 4-stelliges Jahr | 2025 |
yy | 2-stelliges Jahr | 25 |
MM | Monat (2-stellig) | 06 |
dd | Tag (2-stellig) | 15 |
HH | Stunde (24h, 2-stellig) | 14 |
mm | Minute (2-stellig) | 30 |
ss | Sekunde (2-stellig) | 00 |
MMMM | Monatsname (ausgeschrieben) | Juni |
EEE | Wochentag (kurz) | Mo. |
EEEE | Wochentag (ausgeschrieben) | Montag |
Beispiele:
{{#format style="date" pattern="dd.MM.yyyy"}}{{createdAt}}{{/format}}Eingabe: 2025-06-15 → Ausgabe: 15.06.2025
{{#format style="date" pattern="dd.MM.yyyy HH:mm"}}{{createdAt}}{{/format}}Eingabe: 2025-06-15T14:30:00 → Ausgabe: 15.06.2025 14:30
{{#format style="date" pattern="EEEE, dd. MMMM yyyy" locale="de-DE"}}{{date}}{{/format}}Eingabe: 2025-06-15 → Ausgabe: Sonntag, 15. Juni 2025
Eingabe mit Custom-Format (inputFormat)
Wenn deine Daten kein ISO-Datum enthalten, sondern z. B. 15.06.2025, nutze inputFormat:
{{#format style="date" inputFormat="dd.MM.yyyy" pattern="yyyy-MM-dd"}}{{date}}{{/format}}Eingabe: 15.06.2025 → Ausgabe: 2025-06-15
Eingaben werden in dieser Reihenfolge geparst:
- Custom
inputFormat(wenn angegeben) - ISO 8601 (
2025-06-15oder2025-06-15T14:30:00Z) - Unix-Timestamp in Millisekunden
replace
Ersetzt alle Vorkommen eines Textes durch einen anderen.
Attribute:
| Attribut | Beschreibung |
|---|---|
from | Der zu ersetzende Text |
to | Der Ersatztext |
{{#replace from="GmbH" to="AG"}}{{company}}{{/replace}}Daten:
{ "company": "Muster GmbH" }Ergebnis: Muster AG
Text löschen (Ersatz durch leeren String):
{{#replace from=" " to=""}}{{productCode}}{{/replace}}Eingabe: AB 1234 CD → Ausgabe: AB1234CD
each
Iteriert über ein Array oder ein Objekt und gibt den Inhalt für jedes Element aus.
Attribute:
| Attribut | Beschreibung | Standard |
|---|---|---|
data | Pfad zum Array oder Objekt | - |
as | Name der Loop-Variable | entry |
Array von Objekten
{{#each data=users as="user"}} - {{user.firstName}} {{user.lastName}}{{/each}}Daten:
{ "users": [ { "firstName": "Anna", "lastName": "Schmidt" }, { "firstName": "Bob", "lastName": "Müller" } ]}Ergebnis:
- Anna Schmidt - Bob MüllerBedingungen innerhalb von each
Du kannst {#if} innerhalb von {{#each}} verwenden. Die Bedingung wird mit den Daten des aktuellen Elements ausgewertet:
{{#each data=users as="user"}} {#if user.active}✓ {{user.firstName}}{:else}✗ {{user.firstName}}{/if}{{/each}}Optionale Blöcke innerhalb von each
Optionale Blöcke [[ ]] funktionieren ebenfalls innerhalb des Loops:
{{#each data=contacts as="k"}} [[{{k.firstName}} {{k.lastName}}]]{{/each}}Nur Kontakte, bei denen beide Felder vorhanden sind, erscheinen in der Ausgabe.
Objekte iterieren
Bei Objekten wird jedes Schlüssel-Wert-Paar als zweiteiliges Element übergeben:
entry.0→ der Schlüsselentry.1→ der Wert
{{#each data=properties as="e"}} {{e.0}}: {{e.1}}{{/each}}Daten:
{ "properties": { "color": "Blau", "size": "XL" } }Ergebnis:
color: Blau size: XLZugriff auf äußere Daten
Innerhalb des Loops hast du auch Zugriff auf alle Felder außerhalb des Arrays:
{{#each data=articles as="a"}} {{a.name}} - Währung: {{currency}}{{/each}}Pipe-Syntax
Die Pipe-Syntax ist eine kompaktere Alternative zu Block-Funktionen, wenn du einen einzelnen Wert transformieren möchtest. Mehrere Pipes können hintereinandergeschaltet werden.
{{placeholder | function}}{{placeholder | function(attribute="value")}}{{placeholder | function1 | function2}}Verfügbare Pipe-Funktionen
| Funktion | Beschreibung |
|---|---|
uppercase | Wandelt in Großbuchstaben um |
format(...) | Formatiert (Datum, Telefonnummer) |
replace(...) | Ersetzt Text |
Beispiele:
{{name | uppercase}}max mustermann → MAX MUSTERMANN
{{phoneNumber | format(style="phoneNumber")}}+491782367141 → +49 178 2367141
{{date | format(style="date" pattern="dd.MM.yyyy")}}2025-06-15 → 15.06.2025
{{articleName | replace(from=" " to="_") | uppercase}}Artikel Name → ARTIKEL_NAME
Pipes in optionalen Blöcken
Pipes funktionieren auch innerhalb von [[ ]]-Blöcken. Die Block-Gültigkeit richtet sich dabei nach dem Quellwert, nicht nach dem formatierten Ergebnis:
[[{{phoneNumber | format(style="phoneNumber")}}]]Der Block wird weggelassen, wenn phoneNumber fehlt oder leer ist, unabhängig davon, was die Formatierung zurückgeben würde.
Attribute in Pipe-Funktionen
Wie bei Block-Funktionen kannst du Attribute benannt oder positionell übergeben (mehr dazu in Attribute - benannt vs. positionell):
{{date | format(style="date" pattern="dd.MM.yyyy")}} ← benannt{{date | format("date" pattern="dd.MM.yyyy")}} ← style positionell{{text | replace("old", "new")}} ← beide positionellGlobale Variablen
Das System stellt einige eingebaute Variablen unter dem Präfix g. zur Verfügung.
g.now - Aktuelles Datum und Uhrzeit
g.now liefert das aktuelle Datum und die aktuelle Uhrzeit zum Zeitpunkt der Template-Auswertung.
Ausgabe formatieren:
{{g.now | format(style="date" pattern="dd.MM.yyyy")}}Ausgabe: 17.04.2026
{{g.now | format(style="date" pattern="dd.MM.yyyy HH:mm")}}Ausgabe: 17.04.2026 09:45
In Bedingungen verwenden (mehr dazu im nächsten Kapitel):
{#if g.now < "2025-12-31"}Aktion läuft noch{:else}Aktion beendet{/if}Datumsvergleiche
Datumswerte können direkt in Bedingungen verglichen werden. Das System erkennt ISO-8601-Datumsstrings automatisch und vergleicht sie korrekt als Zeitpunkte, nicht als Zeichenketten.
Unterstützte Datumsformate in Bedingungen
| Format | Beispiel |
|---|---|
| ISO-Datum | "2025-12-31" |
| ISO-Datum mit Uhrzeit | "2025-12-31T23:59:59" |
| ISO-Datum mit Zeitzone | "2025-12-31T23:59:59Z" |
Beispiele
Aktionszeitraum prüfen:
{#if g.now >= "2025-01-01" && g.now <= "2025-12-31"} Aktion 2025 ist aktiv{/if}Ablaufdatum aus den Daten prüfen:
{#if contract.validUntil >= g.now} Vertrag ist gültig{:else} Vertrag ist abgelaufen{/if}Zwei Datumsfelder miteinander vergleichen:
{#if delivery.arrival < delivery.planned} Frühzeitig geliefert{:else if delivery.arrival == delivery.planned} Pünktlich geliefert{:else} Verspätet{/if}Attribute - benannt vs. positionell
Attribute in Block-Funktionen und Pipes können auf zwei Arten angegeben werden.
Benannte Attribute
Der Attributname wird explizit angegeben. Reihenfolge spielt keine Rolle.
{{#format style="date" pattern="dd.MM.yyyy"}}{{date}}{{/format}}{{#format pattern="dd.MM.yyyy" style="date"}}{{date}}{{/format}} ← gleichwertigPositionelle Attribute
Der Wert wird in Anführungszeichen ohne Schlüsselname angegeben. Die Reihenfolge legt fest, welchem Parameter der Wert zugeordnet wird.
{{#format "phoneNumber"}}{{phoneNumber}}{{/format}}{{#format "date" pattern="dd.MM.yyyy"}}{{date}}{{/format}}Positionelle Attribute können mit benannten gemischt werden. Benannte Attribute haben immer Vorrang.
Positionelle Reihenfolge je Funktion
| Funktion | Position 0 | Position 1 | Position 2 |
|---|---|---|---|
format | style | locale / country | pattern |
replace | from | to | - |
Kurzschreibweise (Pipe):
{{phoneNumber | format("phoneNumber")}}{{date | format("date" pattern="dd.MM.yyyy")}}{{text | replace("old", "new")}}Bekannte Limitierungen
Verschachtelte {{#each}}-Blöcke
Mehrere ineinander verschachtelte {{#each}}-Blöcke werden aktuell nicht unterstützt. Nur die äußerste Ebene wird korrekt verarbeitet.
{{#each data=categories as="cat"}} {{#each data=cat.articles as="art"}} ← funktioniert nicht {{art.name}} {{/each}}{{/each}}{#if} außerhalb von {{#each}}-Inhalt
Wenn eine Bedingung auf Felder verweist, die nur innerhalb eines {{#each}}-Loops existieren, muss die Bedingung innerhalb des {{#each}}-Blocks stehen, was unterstützt wird. Bedingungen, die Loop-Variablen von außen referenzieren, sind nicht möglich.
Schnellreferenz
Syntax-Übersicht
| Syntax | Beschreibung |
|---|---|
{{field}} | Einfacher Platzhalter |
{{obj.field}} | Verschachteltes Feld |
{{arr[0].field}} | Array-Zugriff per Index |
{{arr(key=val)[0].field}} | Array-Filter |
[[...{{field}}...]] | Optionaler Block (weggelassen wenn leer) |
{#if cond}...{/if} | Bedingung |
{#if cond}...{:else}...{/if} | Bedingung mit Else |
{#if cond}...{:else if cond2}...{:else}...{/if} | Mehrfach-Bedingung |
{{#join delimiter=","}}...{{/join}} | Blöcke verbinden |
{{#uppercase}}...{{/uppercase}} | Großschreibung |
{{#format style="date" pattern="..."}}...{{/format}} | Datumsformatierung |
{{#format style="phoneNumber"}}...{{/format}} | Telefonnummer-Formatierung |
{{#replace from="x" to="y"}}...{{/replace}} | Text ersetzen |
{{#each data=list as="item"}}...{{/each}} | Schleife |
{{field | function}} | Pipe |
{{field | function | function2}} | Pipe-Kette |
g.now | Aktuelles Datum/Uhrzeit |
Vergleichsoperatoren
| Operator | Bedeutung |
|---|---|
== | gleich |
!= | ungleich |
> | größer als |
< | kleiner als |
>= | größer oder gleich |
<= | kleiner oder gleich |
&& | logisches UND |
|| | logisches ODER |
Datumstoken (Auswahl)
| Token | Ausgabe |
|---|---|
yyyy | 2025 |
MM | 06 |
dd | 15 |
HH:mm | 14:30 |
dd.MM.yyyy | 15.06.2025 |
MMMM yyyy | Juni 2025 |
EEEE, dd. MMMM yyyy | Sonntag, 15. Juni 2025 |