Empfängerauswahl (Rezept)¶
Ein häufiges Muster: Ein Picker öffnet eine Auswahl mit Vorname, Nachname, E-Mail und Benutzerkennung. Die Einzelwerte landen in versteckten Feldern, im sichtbaren Feld „Empfänger" steht die Zusammenfassung „Nachname, Vorname (Kennung)". Ein Absenden-Knopf speichert den Datensatz, stempelt Absender und Zeitpunkt und verschickt im Namen des angemeldeten Benutzers eine Mail mit einem Link auf genau diesen Datensatz — danach verschwindet der Knopf, und der Link erscheint.
Das Muster gibt es zweifach:
- als Baukasten-Baustein „Empfängerauswahl" (Ordner Feldgruppen) — legt die ganze Feldgruppe samt Skripten auf einmal an;
- als Beispielformular „Empfängerauswahl (Demo)" (
empfaenger-auswahl, Katalog Demo), installierbar unter System-Administration → Formular-Bausteine → Beispiele.
Diese Seite erklärt die Bausteine zum Verstehen und Nachbauen.
Baukasten-Baustein: alles kommt beim Ablegen mit
Beim Ablegen bekommen alle Feldnamen ein Präfix
(empfaenger → empf_empfaenger). Der Baukasten schreibt dabei auch
alle Verweise um: Zielfelder in kc:picker.set, Feldnamen in
kc:visibleIf/kc:requiredIf, Makros wie ${value:empfaenger} und die
Feldnamen in den mitgelieferten Skripten (onBeforeSave,
onSubmit). Außerdem setzt er kc:reflectServerValues am Formular.
Gibt es am Formular schon ein gleichnamiges Skript, wird der Block des Bausteins mit einer Markierung angehängt (nicht überschrieben), und ein Hinweis nennt das zu prüfende Skript. Nach dem Ablegen nur noch Speichern — fertig.
Die Bausteine¶
1. Der Picker (Feld „Empfänger")¶
Der Picker sitzt auf dem sichtbaren Feld empfaenger. Quelle ist die
KCForms-Benutzertabelle USERS im table-Modus — also komplett im
Reiter Auswahl zusammenklickbar. Die Zusammenfassung entsteht über
eine Textvorlage, das Auswahldatum über das Sondertoken @today:
"empfaenger": {
"type": "string", "title": "Empfänger", "kc:readonly": true,
"kc:maxLength": 160, "kc:placeholder": "Über … auswählen",
"kc:lookupActiveIf": "kc.isEmpty(abgesendetAm)",
"kc:picker": {
"title": "Empfänger auswählen",
"table": "USERS",
"where": "ACC_STATUS = 1",
"orderBy": "LAST_NAME, FIRST_NAME",
"search": ["FIRST_NAME", "LAST_NAME", "EMAIL", "LOGIN_NAME"],
"columns": [
{ "column": "FIRST_NAME", "title": "Vorname" },
{ "column": "LAST_NAME", "title": "Nachname" },
{ "column": "EMAIL", "title": "E-Mail" },
{ "column": "LOGIN_NAME", "title": "Benutzerkennung" }
],
"pageSize": 10,
"set": {
"empfaenger": "{LAST_NAME}, {FIRST_NAME} ({LOGIN_NAME})",
"empfVorname": "FIRST_NAME",
"empfNachname": "LAST_NAME",
"empfEmail": "EMAIL",
"empfKennung": "LOGIN_NAME",
"empfAuswahlDatum": "@today"
}
}
}
table+where: Basis-Tabelle plus fester Filter; die Suche verknüpft der Server perAND.set: Zielfeld ← Quelle — eine Spalte, eine Textvorlage mit{SPALTE}-Platzhaltern oder ein Sondertoken (@today,@now).- Das Feld ist
kc:readonly— gewählt wird nur über den Picker. kc:lookupActiveIf: "kc.isEmpty(abgesendetAm)"sperrt die Auswahl nach dem Versand: SobaldabgesendetAmgefüllt ist, verschwindet der …-Knopf.
Andere Quelle statt USERS (siehe Picker):
- LDAP/AD:
"ldapConnector": "<name>", optionalldapBase/ldapFilter;columns/setauf LDAP-Attribute (givenName,sn,mail,uid). - Externe Datenbank: zusätzlich
"dataSourceId": <id>zutable/sql.
2. Die versteckten Felder¶
kc:visible: false blendet ein Feld aus, behält aber den Wert (kein
kc:clearIfInvisible setzen):
"empfVorname": { "type": "string", "title": "Vorname (Empfänger)", "kc:maxLength": 80, "kc:visible": false },
"empfNachname": { "type": "string", "title": "Nachname (Empfänger)", "kc:maxLength": 80, "kc:visible": false },
"empfEmail": { "type": "string", "title": "E-Mail (Empfänger)", "kc:maxLength": 120, "kc:visible": false },
"empfKennung": { "type": "string", "title": "Benutzerkennung (Empfänger)", "kc:maxLength": 80, "kc:visible": false },
"empfAuswahlDatum": { "type": "string", "format": "date", "title": "Datum der Empfängerauswahl", "kc:visible": false }
format: "date" erzeugt eine DATE-Spalte. kc:maxLength legt die
Spaltenbreite fest (ohne Angabe VARCHAR(255)).
Versteckte Felder im Formular-Editor sehen
In der Vorschau des Formular-Editors blendet der Schalter Ausgeblendete anzeigen solche Felder zum Bearbeiten ein.
3. Versand-Felder und Absenden-Knopf¶
„Abgesendet von/am" sind sichtbar und schreibgeschützt — sie werden
gestempelt, nicht getippt. Der Datensatz-Link erscheint erst, wenn er
gefüllt ist. Der Knopf löst die normale Speicherung aus
(scriptHook: "saveForm") und ist nur sichtbar, solange abgesendetAm
leer ist:
"abgesendetVon": { "type": "string", "title": "Abgesendet von", "kc:maxLength": 120, "kc:readonly": true },
"abgesendetAm": { "type": "string", "title": "Abgesendet am", "kc:maxLength": 20, "kc:readonly": true },
"absenderKennung": { "type": "string", "title": "Benutzerkennung (Absender)", "kc:maxLength": 80, "kc:visible": false },
"datensatzLink": {
"type": "string", "title": "Link zum Datensatz", "kc:maxLength": 300,
"kc:readonly": true, "kc:colspan": "full",
"kc:visibleIf": "!kc.isEmpty(datensatzLink)"
},
"btn_absenden": {
"type": "string", "title": "", "kc:colspan": "full",
"kc:button": { "label": "Absenden", "variant": "primary", "scriptHook": "saveForm" },
"kc:tooltip": { "text": "Absenden an ${value:empfaenger}" },
"kc:visibleIf": "kc.isEmpty(abgesendetAm)"
}
Am Schema-Root steht "kc:reflectServerValues": true: Der Server
spiegelt die in den Skripten gesetzten Werte (Stempel und Link) zurück in
die Maske. Nur so verschwindet der Knopf sofort nach dem Versand und der
Link wird sichtbar, ohne den Datensatz neu zu laden.
Tooltip nennt den Empfänger
kc:tooltip.text darf Makros enthalten: ${value:empfaenger} zeigt zur
Laufzeit den aktuellen Feldwert — der Tooltip lautet dann etwa
„Absenden an Bauer, Tobias (tbauer)".
Zweispaltiges Layout
Der Abschnitt trägt kc:sectionLayout: "horizontal-2". Ohne
kc:colspan belegt ein Feld eine Spalte: Empfänger steht links mit
einem kc:spacer daneben, darunter Abgesendet von / am
nebeneinander. Der Knopf spannt mit kc:colspan: "full" über beide
Spalten.
4. Die Skripte¶
„Absenden" ist eine normale Speicherung. Die Logik verteilt sich auf zwei Skripte der Speicher-Pipeline, weil der Link erst nach dem Speichern gebaut werden kann (er braucht die Datensatz-ID):
onBeforeSaveläuft vor dem Speichern. Ist ein Empfänger gewählt und noch nicht abgesendet, stempelt es Absender und Zeitpunkt — diese Werte werden mitgespeichert. Das Hilfsfeld_sendNowsignalisiertonSubmitden Versand (Felder mit_stehen nicht im Schema und werden weder gespeichert noch zurückgespiegelt).
// onBeforeSave
if (ctx.form.empfEmail && !ctx.form.abgesendetAm) {
ctx.form.abgesendetVon = macros.resolve('${user:lastName}, ${user:firstName} (${user:name})');
ctx.form.abgesendetAm = macros.resolve('${datetime(dd.MM.yyyy HH:mm)|now}');
ctx.form.absenderKennung = macros.resolve('${user:name}');
ctx.form._sendNow = true;
}
onSubmitläuft nach dem Speichern (ctx.instanceIdist gesetzt). Es baut den Link auf diesen Datensatz (mail.newAdhocInvocation), trägt ihn mitctx.persist('datensatzLink')nach und mailt ihn im Namen des angemeldeten Benutzers:
// onSubmit
if (ctx.form._sendNow) {
var inv = mail.newAdhocInvocation('any'); // { id, url } — Link auf diesen Datensatz
ctx.form.datensatzLink = inv.url;
ctx.persist('datensatzLink'); // Link in die gespeicherte Zeile nachtragen
var msg = mail.newMessage();
if (ctx.user && ctx.user.email) { msg.from = ctx.user.email; }
msg.to = ctx.form.empfEmail;
msg.subject = 'Zustellung aus KCForms';
msg.text = 'Hallo ' + (ctx.form.empfVorname || '') + ',\n\n'
+ 'Empfänger: ' + ctx.form.empfaenger + '\n'
+ 'Link zum Datensatz: ${url}\n';
mail.send(msg, inv); // ersetzt ${url} durch inv.url
}
Absender und Freigabeliste
msg.from = ctx.user.email verschickt im Namen des Anwenders. Der
Mailserver muss diese Absenderadresse zulassen (viele Anbieter erlauben
nur Adressen des angemeldeten Postfachs) — sonst kommt ein
Zustellfehler
zurück. Die Empfänger-Domain muss ggf. auf der
Empfänger-Freigabeliste stehen.
Nachbauen — Schritt für Schritt¶
- Felder anlegen:
empfaenger(mit dem Picker oben), die fünf verstecktenempf*-Felder,abgesendetVon,abgesendetAm,absenderKennung,datensatzLink,btn_absenden(scriptHook: "saveForm"). - Am Schema-Root
"kc:reflectServerValues": truesetzen. - Im Reiter Skripte
onBeforeSave(Stempel) undonSubmit(Link und Mail) anlegen. - Fertig — der Picker füllt Zusammenfassung und versteckte Felder, Absenden speichert, stempelt, mailt den Link und verschwindet.
Schneller: den Baukasten-Baustein ziehen oder das Beispielformular
empfaenger-auswahl duplizieren.