Makros (${…})¶
KCForms-Makros sind kleine Platzhalter im Format ${klasse:attribut},
die an der Render-Zeit durch dynamische Werte ersetzt werden. Sie sparen
ein eigenes onLoad-Skript ein, wenn man bloß den angemeldeten Benutzer
oder eine andere bekannte Größe in einem Leittext / Vorgabewert / Footer
einbauen möchte.
Die Makros werden an diesen Stellen aufgelöst:
| Ort | Auflösung |
|---|---|
Skripte (macros.resolve(...)) |
Server (MacroService) |
| Web-Formular (Leittexte, Titel, Tooltips …) | Browser (macros.ts, Spiegel des Servers) |
| PDF (Leittexte, Titel, Kopf- und Fußzeilen) | Server |
kc:defaultValue beim Öffnen |
Server |
Browser und Server kennen dieselben Klassen — ein im PDF aufgelöstes
${user:firstName} ergibt im Browser dasselbe.
Syntax¶
${klasse:attribut} ${user:firstName}
${klasse:a:b} ${attachment:0:name}
${modifier|klasse:attribut} ${upper|user:lastName}
${date|now}
${escape|user:lastName}
Unauflösbare Makros werden zu einem leeren String — eine Tippfehler- Klasse zerstört also nicht den ganzen Leittext.
Verfügbare Klassen¶
system¶
| Makro | Wert |
|---|---|
${system:id} |
Umgebungs-Id aus app_settings.system.id (z. B. Prod, Dev, QS) |
${system:engine} |
konstant server — KCForms hat keine Filler-/Portlet-Variante |
${system:isServer} |
konstant true |
${system:isFiller} |
konstant false |
${system:isPortlet} |
konstant false |
${system:product} |
konstant KCForms |
${system:release} |
Version aus kcforms.version (Spring-Property) |
session¶
| Makro | Wert |
|---|---|
${session:id} |
Servlet-Session-ID (im Frontend leer) |
${session:locale} |
Browser-Locale (de_DE, en_US, …) |
${session:locale.language} |
Nur der Sprach-Anteil (de, en, …) |
${session:remoteAddress} |
Client-IP (im Frontend leer) |
${session:creationTime} |
Zeitstempel des Session-Starts (im Frontend leer) |
user¶
| Makro | Wert |
|---|---|
${user:id} |
Login-Name (Aliase: idUser, name) |
${user:firstName} |
Vorname aus dem User-Profil |
${user:lastName} |
Nachname aus dem User-Profil |
${user:emailAddress} |
E-Mail-Adresse (Alias: email) |
${user:locale} |
Voreingestellte Locale aus dem Profil |
${user:lastLogin} |
ISO-Zeitstempel der letzten Anmeldung |
${user:client} |
Mandanten-Id (sofern gepflegt) |
form¶
| Makro | Wert |
|---|---|
${form:id} |
Form-Id (z. B. bestellung) |
${form:folder} |
Katalog-Ordner |
${form:info.title} |
Titel aus dem Schema |
${form:info.description} |
Beschreibung aus kc:description |
${form:info.version} |
Version (V0001 etc.) |
${form:info.versionName} |
Optionaler Versions-Name aus meta.versionName |
${form:info.versionDisplay} |
Kombiniert: Pilot (V0001) |
${form:info.shortTitle} |
Kurztitel aus meta.shortTitle |
${form:info.author} |
Autor (Schema-Author bzw. meta.author) |
${form:info.validFrom} |
Aus meta.validFrom, falls gesetzt |
${form:info.validTo} |
Aus meta.validTo, falls gesetzt |
value¶
Im Frontend ist das reaktiv — jeder Tastendruck im Feld aktualisiert
auch alle Leittexte, die ${value:…} enthalten. Ein vorangestelltes ../
wird ignoriert (${value:../foo} = ${value:foo}).
param¶
${param:…} liefert die Properties des
Formulars (bzw. globale Properties) — dieselben Werte, die Skripte als
ctx.params.<name> sehen. So lassen sich Grenzwerte, Adressen oder
Hinweistexte pflegen, ohne das Formular zu ändern.
instance¶
| Makro | Wert |
|---|---|
${instance:index} |
0-basiert; -1 bei einem neuen, ungespeicherten Datensatz |
${instance:index1} |
1-basiert (0 bei neuem Datensatz) |
${instance:isNew} |
true/false als String |
${instance:isModified} |
true, sobald der Anwender getippt hat |
${instance:count} |
Anzahl Datensätze in der aktuellen Liste; -1 wenn unbekannt |
${instance:key} |
String-Repräsentation des Primary-Keys |
attachment¶
| Makro | Wert |
|---|---|
${attachment:count} |
Anzahl der Anhänge |
${attachment:countVisible} |
Anzahl sichtbarer Anhänge |
${attachment:0} |
Default-URL (/api/attachments/{id}/download) |
${attachment:0:name} |
Dateiname der ersten Anlage |
${attachment:0:nameWithoutExtension} |
Name ohne Dateiendung |
${attachment:0:extension} |
Dateiendung in Großbuchstaben |
${attachment:0:contentType} |
Mime-Type |
${attachment:0:uuid} |
UUID, falls vorhanden |
${attachment:<uuid>:name} |
UUID-basierter Lookup |
document (nur PDF)¶
| Makro | Wert |
|---|---|
${document:page} |
Aktuelle Seitenzahl (1-basiert) — nur sinnvoll im Footer |
${document:pages} |
Gesamtseitenzahl |
Verwendung in Kopf- und Fußzeilen, z. B.:
Kopf- und Fußzeilen zeichnet KCForms erst, wenn der Inhalt fertig ist —
deshalb kennt ${document:pages} die endgültige Seitenzahl. In Leittexten
bleiben die beiden Makros leer. Kopf- und Fußzeilen lassen sich auch
zentral als Druckvorlage
pflegen.
i18n — sprachabhängige Beschriftungen¶
${i18n:<schlüssel>} liefert ein lokalisiertes Standard-Wort in der
aktuellen Anzeige-/Dokumentsprache. So bleibt der Zahlenwert bei
${document:page}/${document:pages}, die Wörter drumherum kommen aus
einem eingebauten Wörterbuch (das übliche Report-Muster: numerische Tokens +
Resource-Bundle). Beispiel für einen sprachneutralen Footer:
→ „Seite 1 von 3" (de) · „Sida 1 av 3" (sv) · „Page 1 of 3" (en).
| Schlüssel | de | sv | en |
|---|---|---|---|
page / pages |
Seite / Seiten | Sida / Sidor | Page / Pages |
of |
von | av | of |
printDate / printedOn |
Druckdatum / gedruckt am | Utskriftsdatum / utskrivet den | Print date / printed on |
sendDate / sentOn |
Versendedatum / versendet am | Skickat den / skickat den | Sent date / sent on |
date / dateTime / time |
Datum / Datum-Zeit / Uhrzeit | Datum / Datum-tid / Tid | Date / Date-time / Time |
form / author / version |
Formular / Autor / Version | Formulär / Författare / Version | Form / Author / Version |
createdOn / no |
erstellt am / Nr. | skapad den / Nr | created on / No. |
sheet / sheets |
Blatt / Blätter | Blad / Blad | Sheet / Sheets |
Datumswerte kombinierst du mit dem locale-fähigen ${date|…}, z. B.
${i18n:printDate}: ${date(dd.MM.yyyy)|now} → „Druckdatum: 15.07.2026" /
„Utskriftsdatum: 2026-07-15".
Welche Uhr gilt: now ist der Zeitpunkt auf dem Server. In welcher
Zeitzone er ausgegeben wird, legt der Administrator unter System-Einstellungen
→ Zeitzone für Datums- und Zeitangaben fest. Ohne Einstellung gilt die Uhr
des Servers — siehe Welche Uhr gilt?
Sprachquelle: Im Web-Formular folgt ${i18n:…} dem Sprach-Umschalter
(Ansichtssprache). Im PDF folgt es der Render-Sprache — beim Ausdruck die
UI-Sprache, bei mail-/pdf-Skripten die Skript-Sprache ctx.lang (z. B. die
Empfänger-Sprache). Unbekannte, aber sinnvolle Sprachen fallen auf Deutsch
zurück; ein unbekannter Schlüssel wird sichtbar als Klartext ausgegeben
(Tippfehler-Hinweis).
Ebenfalls sprachabhängig im PDF: ${form:info.title} — liegt für das
Formular eine Titel-Übersetzung vor, erscheint sie im PDF-Kopf in der
Render-Sprache (sonst der Basistitel).
env¶
${env:os.name} Aus System.getProperty("os.name")
${env:java.version} Aus System.getProperty("java.version")
${env:java.vendor} …
Funktioniert nur im PDF und im Skript-Binding — der Browser hat keinen
Zugriff auf System-Properties und liefert für ${env:…} leer zurück.
Bewusst werden nur Java-System-Properties unterstützt, keine ENV-
Variablen — die enthalten oft Secrets (DB-URLs, Passwörter), die nicht
versehentlich in einem Leittext landen sollen.
Modifier¶
Modifier kommen vor dem Klassen-Body, getrennt durch einen senkrechten
Strich (|):
| Modifier | Wirkung |
|---|---|
${upper|…} |
toUpperCase |
${lower|…} |
toLowerCase |
${escape|…} |
SQL-Quote: ' verdoppeln, äußere Single-Quotes setzen |
${date|…} |
Datum als yyyy-MM-dd. Akzeptiert ISO-Strings oder das Literal now |
${time|…} |
Zeit als HH:mm:ss |
${datetime|…} |
yyyy-MM-dd HH:mm:ss |
Eigenes Format-Pattern¶
Alle Datums- und Zeit-Modifier können ein eigenes Format-Pattern in Klammern
tragen — die Syntax folgt dem Java
SimpleDateFormat.
Wer ohne Klammern aufruft, bekommt das Default-Pattern (siehe Tabelle oben).
${date(dd.MM.yyyy)|now} 06.05.2026
${time(HH:mm)|now} 14:32
${datetime(yyyy/MM/dd HH:mm)|user:lastLogin} 2026/05/06 14:32
${datetime(EEEE, dd. MMMM yyyy 'um' HH:mm)|now} Mittwoch, 06. Mai 2026 um 14:32
${format(dd.MM.yyyy)|user:lastLogin} 06.05.2026
Wichtigste Pattern-Token im Schnellüberblick:
| Token | Bedeutung |
|---|---|
yyyy |
Vierstelliges Jahr |
yy |
Zweistelliges Jahr |
MM |
Monat (zweistellig, z. B. 05) |
MMM |
Monatsname kurz (Mai) |
MMMM |
Monatsname lang (Mai/Januar) |
dd |
Tag (zweistellig) |
HH |
Stunde 0–23 |
hh |
Stunde 1–12 |
mm |
Minute |
ss |
Sekunde |
EEE |
Wochentag kurz (Mi) |
EEEE |
Wochentag lang (Mittwoch) |
'…' |
Literaler Text in einfachen Hochkommas |
Innerhalb der Klammern darf jedes Zeichen außer ) stehen. Wer eine
schließende Klammer im Format-String braucht, splittet das Makro und
ergänzt die Klammer als reinen Literal-Text drumherum.
Beispiele für reine Modifier ohne Format-Argument:
${upper|user:lastName} KEHRMANN
${escape|user:lastName} 'Kehrmann' (für SQL)
${date|now} 2026-05-03
${datetime|value:erstelltAm} 2026-05-03 14:30:00
Wo verwenden?¶
Macros werden überall dort ersetzt, wo der Renderer einen "präsentierten"
String anfasst — Eingabe-Werte (also der Inhalt eines Inputs) bleiben
absichtlich unangetastet, sonst könnte man ${...} nie als wirklichen
Wert eingeben.
| Schema-Feld | Frontend | Beim Öffnen | |
|---|---|---|---|
title (Field-Label) |
✓ | ✓ | — |
description (Section) |
✓ | — | — |
kc:text.content |
✓ | ✓ | — |
kc:link.text / kc:link.url |
✓ | — | — |
kc:button.label |
✓ | — | — |
kc:section.title |
✓ | — | — |
Form-title |
(Header) | ✓ | — |
kc:document.title/author/footer |
— | ✓ | — |
kc:pages.*.title |
— | ✓ | — |
kc:defaultValue |
— | — | ✓ |
Skripte¶
Im Skript steht macros als Top-Level-Binding bereit:
var begruessung = macros.resolve("Hallo ${user:firstName}!");
ctx.form.greeting = begruessung;
// Debug-Helper — zeigt den aktuellen MacroContext
log.info(JSON.stringify(macros.debug(), null, 2));
Im Skript sieht der Resolver dieselben Werte, die der Renderer auch sehen würde. Wer dynamisch komponiert (z. B. eine Mail-Body-Template), fährt damit gut.
Demo-Formular¶
Das Beispielformular Makros · Live-Auflösung (macros-demo,
installierbar unter System-Administration → Formular-Bausteine →
Beispiele) zeigt alle Makros aufgelöst. Die Eingabefelder sind über
kc:defaultValue vorbelegt — vorname mit ${user:firstName},
nachname mit ${user:lastName}, referenz mit REF-${user:id}. Beim
Drucken läuft auch die Fußzeile Seite ${document:page} von
${document:pages} mit.