Scripting-Überblick¶
Skripte machen Formulare lebendig. Sie sind in JavaScript
(ECMAScript 2022, GraalVM) geschrieben und laufen auf dem Server in
einer Sandbox. Browser-Funktionen (window, document, fetch …) gibt es
dort nicht — stattdessen stellt KCForms eine Reihe Host-Objekte bereit
(ctx, db, mail, http …).
Neu im Programmieren?
Zwei Seiten holen dich ohne Vorwissen ab:
JavaScript-Grundlagen — Variablen, Text, Zahlen, Datum,
Entscheidungen, Schleifen, eigene Funktionen — und
JSON und Objekte verstehen, denn alles, was ein Skript
anfasst (ctx.form, Detail-Tabellen, Datenbank-Ergebnisse, Antworten aus
dem Internet), ist ein Objekt.
Lieber erst ausprobieren?
Unter Skripte in Beispielen stehen zu jedem Werkzeug mindestens 20 fertige, getestete Skripte — von der ersten Zeile bis zur Transaktion, in einfachen Worten erklärt.
Hooks am Formular¶
Skripte eines Formulars pflegst du im Formular-Editor im Reiter Skripte
über der Vorschau. Jeder Hook bekommt denselben ctx und dieselben
Host-Objekte.
| Hook | Wann | Typische Aufgabe |
|---|---|---|
onLoad |
Datensatz wird geöffnet | vorbelegen, externe Daten laden |
onFieldChange |
ein Feld wurde verlassen bzw. geändert | Berechnungen, abhängige Werte |
onValidate |
Validieren und vor dem Speichern | Regeln über mehrere Felder |
onBeforeSave |
vor dem Speichern (kann abbrechen) | letzte Aufbereitung, Veto |
onSubmit |
nach erfolgreichem Speichern | Mail, PDF, Dateien, Schnittstellen |
onAfterSave |
am Ende der Speicher-Pipeline (ctx.isNew) |
Folgeaktionen |
onBeforeDelete |
vor dem Löschen (kann abbrechen) | Löschen verhindern |
onAfterDelete |
nach dem Löschen (ctx.deletedId) |
aufräumen, Umsysteme informieren |
Reihenfolge beim Speichern: onValidate → onBeforeSave → [Speichern] →
onSubmit → onAfterSave; beim Löschen onBeforeDelete → [Löschen] →
onAfterDelete. Details: Lifecycle.
Dazu kommen eigene Hooks (beliebiger Name), die eine Schaltfläche
(kc:button mit scriptHook) oder eine Rückfrage auslöst, sowie
die Workflow-Skripte (vor und nach einem Stufenwechsel) und onCopy für Workflows.
Beispiel — onFieldChange schreibt die Summe zweier Felder in ein drittes:
Kürzer mit den $feld-Aliasen, die KCForms für alle Felder des Formulars
anlegt:
Und am kürzesten über das Feld-Handle, das es ebenfalls zu jedem Feld gibt:
.num gibt den Wert als Zahl, .isEmpty beantwortet „nichts eingetragen?",
.error(…) hängt eine Meldung an genau dieses Feld. Übersicht:
field.<name>.
Rechnen ohne Skript
Summen und einfache Rechnungen gehen ohne Skript mit Berechnungsfeldern.
Weitere Skript-Arten¶
| Art | Wo | Besonderheit |
|---|---|---|
| Skript-Konsole | Zahnrad → Skript-Konsole | freie Skripte ohne Formular (Diagnose, Migrationen); ctx.formId ist leer, Testwerte $text, $number, $date, $flag |
| Jobs | Zeitplaner | zeitgesteuert, zusätzlich Binding job — siehe Jobs |
| REST-Services | System-Administration → REST-Services | eigene HTTP-Endpunkte — siehe REST-Services |
| Anmelde-Skripte | Anmeldung per Skript | eigene Login-Logik — siehe Anmeldung |
| Lookup-/Picker-Skripte | kc:lookup.script, kc:picker.script |
liefern Listen über handle({...}) |
| Vorbelegungen | kc:defaultExpression |
ein Ausdruck, volle onLoad-API |
Der ctx-Kontext¶
ctx trägt die Daten des aktuellen Aufrufs — Details in der
ctx-Referenz:
| Pfad | Inhalt |
|---|---|
ctx.form |
Feldwerte (lesen und schreiben); Detail-Tabellen als Listen |
ctx.formId, ctx.instanceId |
Formular-ID, Datensatz-ID (null bei neuem Datensatz) |
ctx.isNew |
true, solange der Datensatz noch nicht gespeichert ist |
ctx.user |
angemeldeter Benutzer (name, firstName, lastName, email, locale, roles = Gruppen, permissions ohne PERM_-Präfix …) |
ctx.lang |
aktuelle Sprache (de, sv, en …) |
ctx.params |
Properties des Formulars |
ctx.attachments |
Dateianlagen des Datensatzes |
ctx.model |
Lese-Sicht auf Datenmodell und Detail-Tabellen |
ctx.addError(feld, text) |
Prüffehler melden |
ctx.cancel(grund) |
Speichern/Löschen abbrechen (in onBefore…) |
ctx.persist(feld…) |
Felder nachträglich in den gespeicherten Datensatz schreiben (onSubmit) |
ctx.requestClose() |
Formular nach dem Hook schließen |
Host-Objekte¶
| Objekt | Zweck | Seite |
|---|---|---|
db |
SQL mit Parametern, auch auf externen Datenquellen (db.on(...)) |
db |
forms |
Datensätze anderer Formulare lesen und anlegen | forms |
log |
Protokoll (info, debug, warn, error) |
kc-Helfer |
kc |
kc.num, kc.text, kc.bool, kc.isEmpty — für alles ohne Feld-Handle |
kc-Helfer |
field |
Handle je Formularfeld: .value, .num, .text, .bool, .isEmpty, .error(…) |
field.<name> |
macros |
Makros auflösen (macros.resolve('${user:firstName}')) |
Makros |
view |
Meldungen und Rückfragen im Formular | view |
pdf, delivery |
PDF erzeugen und ausliefern | |
docx |
Word-Vorlagen füllen, Serienbriefe | docx |
mail |
Mails mit Anlagen und Ad-hoc-Links | |
http, ws |
REST- und SOAP-Aufrufe | HTTP, WebService |
ldap |
Verzeichnis-Abfragen | LDAP |
fs |
Dateien in der Sandbox | fs |
csv, xml, zip |
Formate lesen und schreiben, ZIP-Archive | CSV, ZIP |
encoder |
Ad-hoc-Links erzeugen | Web-Links |
workflow |
Workflow-Informationen des Datensatzes | Workflow |
modules |
Module laden (modules.use(...)), z. B. den CSV-Service |
CSV |
job |
nur in Zeitplaner-Jobs | Jobs |
Sandbox¶
- Ein Skript sieht nur die Objekte oben. Java-Klassen nachladen, direkt auf Dateien oder das Netz zugreifen oder Threads starten kann es nicht.
- Zeitlimit: 6 Sekunden je Lauf (
kcforms.scripting.max-exec-millis), Lookup- und Picker-Skripte mindestens 30 Sekunden. Endlosschleifen werden abgebrochen. Date.prototype.format(muster)undDate.fromString(text, muster)sind eingebaut — formatieren und parsen ohne Bibliothek.returnist überall erlaubt:return;beendet Hooks, Jobs und Konsolen-Skripte vorzeitig; inonBeforeSave/onBeforeDeletebrichtreturn false;den Vorgang ab (siehe Lifecycle).
Beispiel: onSubmit mit Mail und PDF¶
// onSubmit — Bestätigung mit dem Formular als PDF-Anlage
log.info('Bestellung gespeichert: ' + ctx.instanceId);
var mp = new mail.MessageMultipart();
mp.addText('Neue Bestellung — siehe Anlage.');
mp.addOutput('bestellung-' + ctx.instanceId + '.pdf'); // aktuelles Formular als PDF
var msg = new mail.Message();
msg.to = 'orders@example.test';
msg.subject = 'Neue Bestellung #' + ctx.instanceId;
msg.content = mp;
mail.send(msg);
view.add(new view.Message('Die Bestellung wurde versendet.', 'Gesendet'));
Fehlersuche¶
log.info(...)großzügig einsetzen. Skript-Protokolle landen inlogs/script.log(und je Benutzer inlogs/by-user/<login>.log), jede Zeile mit[form:<id>]davor — einsehbar unter System-Administration → Betrieb & Überwachung → System-Logs. In der Docker-Konsole erscheinen sie nicht.- In der Skript-Konsole Schnipsel ausprobieren — mit demselben
db-Zugang wie in Hooks. - Prüffehler vor dem Skript: Die Schema-Prüfung läuft vor
onValidate. Fehlt ein Pflichtfeld, meldet das schon sie.
Weiter¶
- JavaScript-Grundlagen, JSON und Objekte verstehen und XML verstehen und verarbeiten — die Grundlage für alles andere
- ctx-Referenz · Lifecycle · Datenmodell
ctx.model - kc-Helfer —
kc.num,log, Datumsfunktionen,$feld - Bibliotheken — wiederverwendbare Funktionen