Zum Inhalt

view — Dialoge

Mit view zeigt ein Skript Dialoge im Formular an — modal oder als Hinweis-Leiste: Meldungen, Bestätigungen, Fragen mit eigenen Antworten.

Die Dialog-Typen

Objekt Zweck
view.Message Hinweis-/Info-Box, ohne oder mit OK-Knopf
view.Question Frage mit beliebigen Antworten
view.Link anklickbarer Link als Hinweis, z. B. auf eine erzeugte Datei
view.Download modaler Dialog mit Titel und Download-Schaltfläche

Alle vier funktionieren gleich: Du baust ein Objekt mit new und gibst es an view.add(…). Alle Dialoge eines Skript-Laufs sammelt KCForms und zeigt sie nach dem Lauf im Formular an.

view.Link und view.Download akzeptieren nur Adressen innerhalb von KCForms (beginnend mit /) — typisch eine Download-Adresse aus pdf/delivery:

var url = pdf.render().deliver('antrag.pdf');

// dezenter Hinweis mit Link
view.add(new view.Link(url, 'Antrag als PDF öffnen'));

// oder prominent, mit Titel und Schaltfläche
view.add(new view.Download(url, 'Antrag herunterladen', 'Dokument erzeugt'));

Frühere Schreibweise: view.embedLink / view.embedDownload

Vor dem Stand vom 26.09.2026 hießen die beiden view.embedLink(url, text) und view.embedDownload(url, text [, titel]) — zwei Verben neben zwei Substantiven. Das embed-Präfix stammte aus der Kompatibilität zu einem übernommenen Skript-Dialekt.

Die alten Namen funktionieren unverändert weiter und erzeugen exakt denselben Dialog — beide Wege gehen durch dieselbe Stelle im Code, ein Test hält das fest. Bestehende Formulare müssen also nicht angefasst werden; für neue Skripte ist die Objekt-Schreibweise die empfohlene.

view.embedScript(code) gibt es nur, damit übernommene Skripte nicht abbrechen: Der Aufruf wird protokolliert, der Code aber nicht ausgeführt.

view.Message — Info-Boxen

Drei Konstruktoren:

new view.Message("Daten gespeichert.");
new view.Message("Daten gespeichert.", "Erfolg");
new view.Message("html:<b>Wichtig</b>", "Hinweis", {
  modal: true, closable: true, okButton: true
});
Property Typ Wirkung
text String Body — html:-Prefix → HTML, sonst Plain
caption String Titel
modal Boolean Backdrop, blockiert Interaktion
closable Boolean Schließen-X oben rechts
okButton Boolean OK-Knopf anzeigen
color String semantische Farbe — "red", "green", …
styleClass String freie CSS-Klasse
iconName String Symbol

Setzbar entweder über die Optionen-Map im 3. Konstruktor-Argument oder per Property-Zuweisung:

var m = new view.Message("Bitte wählen Sie eine Option.");
m.modal = true;
m.color = "red";
m.okButton = true;
view.add(m);

html:-Prefix

Beginnt der text mit html:, wird der Rest als HTML angezeigt. Ohne Präfix ist der Inhalt reiner Text; Zeilenumbrüche bleiben erhalten.

new view.Message("html:Bitte <a href='/help' target='_blank'>Hilfe</a> beachten.");

Eingaben der Anwender trotzdem umwandeln

Seit dem Stand vom 18.10.2026 säubert KCForms html:-Texte vor der Anzeige mit derselben Regel wie Leittexte: Skripte, Event-Handler, eingebettete Seiten und javascript:-Links fallen weg; Formatierung, Listen und gewöhnliche Links bleiben. Werte, die Anwender eingegeben haben, baust du trotzdem nur umgewandelt ein (<, >, &, siehe Beispiel 14) — sonst kann jemand eigene Formatierung oder einen Link in deinen Dialog setzen.

view.Question — Fragen mit Antworten

Eine Frage hat einen Body, einen Titel und eine Liste Antworten mit eigenen Callbacks:

var q = new view.Question("Wirklich speichern?", {
  caption: "Speichern",
  modal: true
});
q.add(new q.Answer("yes", "Ja",   "antwortJa"));    // String → Hook
q.add(new q.Answer("no",  "Nein", function() { log.info("Nein geklickt"); }));
q.defaultAnswer = "yes";
view.add(q);

Vier Vorbelegungen — OK / YES / NO / CANCEL

Jede Question hat fertige Antwort-Instanzen, denen man nur den Callback geben muss:

var q = new view.Question("Schließen?");
var yes = q.YES;  yes.callback = function() { ctx.requestClose(); };
var no  = q.NO;
q.add(yes);
q.add(no);
view.add(q);
Antwort id label
q.OK "ok" „OK"
q.YES "yes" „Ja"
q.NO "no" „Nein"
q.CANCEL "cancel" „Abbrechen"

Die Vorbelegungen sind per Question-Instanz — wenn du in einem Skript zwei Fragen mit jeweils eigenem q.YES baust, sind das zwei unabhängige Antwort-Instanzen. Kein versehentliches Sharing.

Callback-Varianten

Für jeden Answer.callback gibt es drei Möglichkeiten. Wichtig: Wenn der Anwender klickt, ist das Skript, das die Frage gestellt hat, längst beendet.

Callback ist … Was passiert beim Klick?
JS-Funktion Funktion wird sofort beim view.add(...) ausgeführt — nicht erst beim Klick
String Name eines Hooks; beim Klick ruft das Formular diesen Hook mit dem aktuellen Stand der Felder auf
null Klick dismissed nur den Dialog, kein Roundtrip

Klassisches Pattern: alles, was nach dem Klick passieren soll, in einen eigenen Hook packen und dort als Hook-Name eintragen:

// onSubmit-Hook
var q = new view.Question("Möchten Sie eine Bestätigung per Mail?");
q.add(new q.Answer("ja",   "Ja, bitte",         "sendBestaetigungsMail"));
q.add(new q.Answer("nein", "Nein, danke", null));
view.add(q);

// Eigener Hook "sendBestaetigungsMail"
mail.send({ to: ctx.user.email, subject: "Bestellung", body: "Danke!" });

Solche Hooks legst du im Formular-Editor im Reiter Skripte über + Hook hinzufügen mit freiem Namen an.

ctx.requestClose() als Inline-Callback

Der häufigste Inline-Callback ist „Form schließen":

var q = new view.Question("Wirklich verwerfen und schließen?", { modal: true });
var yes = q.YES;  yes.callback = function() { ctx.requestClose(); };
var no  = q.NO;
q.add(yes); q.add(no);
view.add(q);

Hier funktioniert der Inline-Callback-Modus elegant: requestClose setzt einen Flag, den der Server in dieselbe Antwort einbaut. Das Frontend liest den Flag und schließt das Formular.

Trotzdem: nur EINMAL ausgeführt

Inline-Callbacks laufen direkt beim Aufbau des Dialogs — nicht beim Klick. In dem requestClose-Beispiel oben schließt das Formular also immer, sobald der Skript-Run vorbei ist — egal ob der User „Ja" oder „Nein" klickt. Genau für diesen Anwendungsfall ist das ok; für Klick-spezifische Logik nimm Hook-Names statt Inline-Funktionen.

Modale vs. nicht-modale Dialoge

Eigenschaft modal: true modal: false (Default)
Backdrop grauer Vorhang nein
Position mittig im Viewport Banner oben am Form
Andere Aktionen blockiert parallel möglich
Mehrere reihen sich auf reihen sich auf
Geschlossen wird per Button / Backdrop per X (wenn closable)

Banner-Mode ist nützlich für Hinweise, die parallel zum Formular-Editieren sichtbar bleiben sollen. Modal ist für „Antwort zwingend erforderlich".

Vollständiges Beispiel: Lösch-Workflow

// Hook "askDelete" (am Knopf "Löschen")
var q = new view.Question(
  "Datensatz #" + ctx.instanceId + " wirklich löschen?",
  { caption: "Löschen", modal: true, color: "red" }
);

var yes = q.YES;
yes.callback = "doDelete";   // String → triggert eigenen Hook

var no = q.CANCEL;            // null-Callback → einfach dismissen

q.add(yes);
q.add(no);
q.defaultAnswer = "cancel";
view.add(q);

// Hook "doDelete"
forms.delete(ctx.formId, ctx.instanceId);   // räumt auch Anlagen und Detail-Zeilen ab
view.add(new view.Message("Gelöscht.", "Erfolg", { okButton: true }));
ctx.requestClose();

Was hier passiert:

  1. User klickt „Löschen" → askDelete-Hook läuft, baut die Frage, schickt sie ans Frontend.
  2. Frontend rendert modal mit „Ja"/„Abbrechen".
  3. Klickt der Anwender „Ja", läuft der Hook doDelete — ein neuer Skript-Lauf mit derselben ctx.instanceId.
  4. doDelete löscht aus der DB, zeigt die Erfolgsmeldung, requestClose() schließt das Form.

Stolperfallen

  • Inline-Funktion erwartet Klick-Verhalten → falsch. Inline-Funktionen laufen sofort. Für eine Reaktion auf den Klick den Namen eines Hooks angeben.
  • q.add(q.YES) ohne Callback → das ist erlaubt und schließt beim Klick einfach den Dialog. Wenn du eine Reaktion willst, vorher q.YES.callback = "..." oder q.YES.callback = function() {...}.
  • view.add mit etwas anderem als Message/Question → Fehler. view.add(null) wird still ignoriert.
  • new nicht vergessen — view.Message("…") ohne new schlägt fehl.
  • Mehrere Dialoge aus einem Hook → erlaubt; das Frontend rendert alle in einem Stack. Aber: alle Inline-Funktionen feuern unmittelbar.