Validierung & Formate¶
Damit keine unbrauchbaren Daten im System landen, prüft KCForms jede Eingabe, bevor sie gespeichert wird. Als Formular-Autor legst du fest, was geprüft wird — auf drei Wegen:
- Regeln am Feld — Pflicht, Typ, Länge, erlaubte Auswahlwerte, Muster, Datumsformat und Datumsvergleiche. Das deckt die meisten Fälle ab.
- Feld-Validatoren (
kc:validator) — freigegebene Prüffunktionen aus Bibliotheken (IBAN, USt-IdNr. …), live im Browser und verbindlich auf dem Server. - Ein
onValidate-Skript — für Geschäftsregeln, die sich mit den Regeln am Feld nicht ausdrücken lassen, etwa „bei Rabatt ist eine Begründung nötig".
Zusammenklicken reicht — das JSON ist zum Nachschauen da
Pflichtfelder, Längen, Auswahllisten, Muster, Zahlenformate und
Datumsvergleiche richtest du vollständig im Formular-Editor ein, ohne eine
Zeile zu tippen. Die eingeklappten Kästen „Hinter den Kulissen" auf dieser
Seite zeigen, was der Editor dabei in das Formular schreibt. Aufklappen
lohnt sich, wenn du wissen willst, warum eine Prüfung anschlägt — oder
warum sie ausbleibt — und wenn du ein Formular exportieren und in einer
anderen Umgebung wieder einspielen willst. Nur die eigenen Geschäftsregeln
im Abschnitt onValidate-Skript
verlangen wirklich getippten Code.
Geprüft wird nicht erst beim Speichern: Schon wenn der Anwender ein Feld verlässt, meldet das Formular einen falschen Wert. Der Pflicht-Check bleibt dabei außen vor — sonst wäre jedes noch leere Feld sofort rot. Ein Pflichtfeld leer zu lassen, ist eben nicht dasselbe, wie es leer zu speichern: Die Live-Prüfung warnt nur, wenn ein eingegebener Wert falsch ist.
Im Formular-Editor
Sofort serverseitig validieren (beim Verlassen) im Reiter
Sichtbarkeit der Feld-Eigenschaften setzt
kc:serverValidateOnChange. Dann läuft schon beim Verlassen des Feldes die
vollständige Prüfung inklusive onValidate, nicht nur die dieses einen
Feldes.
Regeln, die du am Feld einstellst¶
Pflichtfelder¶
Ein Feld als Pflichtfeld zu markieren, heißt: Der Server nimmt den
Datensatz ohne Wert nicht an. Dynamische Pflicht — „nur nötig, wenn …" — legst
du über kc:requiredIf fest; auch die prüft der Server.
Nicht geprüft werden:
- unsichtbare Felder (
kc:visible: falseoderkc:visibleIffalsy), - schreibgeschützte Felder (
kc:readonly) — sie füllt das System.
Hinter den Kulissen: Pflichtfelder im Schema
{
"required": ["name", "email"],
"properties": {
"name": { "type": "string", "title": "Name" },
"email": { "type": "string", "title": "E-Mail", "format": "email" }
}
}
JSON-Schema-Standard: Die Liste required neben properties nennt die
Pflichtfelder. Alternativ kc:required: true direkt am Feld — gleiche
Wirkung.
Ankreuzfelder: beantwortet oder zugestimmt?¶
Bei einem Ankreuzfeld gibt es zwei verschiedene Ansprüche, und Pflichtfeld allein meint den schwächeren:
| Einstellung | Erfüllt durch | Gedacht für |
|---|---|---|
| Pflichtfeld | Haken oder kein Haken — nur „nie beantwortet" fehlt | „Newsletter? ja/nein" |
Zustimmung erzwingen (kc:requiredTrue) |
nur den gesetzten Haken | „AGB gelesen", „Richtigkeit bestätigt" |
Der Grund für die Trennung: Bei einer Frage wie „Newsletter abonnieren?" ist „nein" eine Antwort — dort darf der Satz ohne Haken gespeichert werden. Bei einer Bestätigung darf er das nicht. Welcher Fall vorliegt, weiß nur du als Designer, deshalb sind es zwei Einstellungen und nicht eine.
„Zustimmung erzwingen" schließt die Pflicht ein — du brauchst nicht beides anzuklicken. Ein noch unbeantwortetes Feld meldet „Pflichtfeld", ein abgewähltes „Bitte bestätigen".
Wenn du ein Bestätigungs-Häkchen aus einer älteren Fassung hast
Dort stand vermutlich nur Pflichtfeld — und das ließ sich mit einem Klick auf das Häkchen und zurück erfüllen. Setze bei solchen Feldern zusätzlich Zustimmung erzwingen; die Einstellung ist absichtlich opt-in, damit bestehende Ja/Nein-Felder unverändert weiterlaufen.
Welcher Typ zugelassen ist¶
type |
Akzeptiert |
|---|---|
"string" |
jeder Text |
"number" |
eine Zahl, auch mit Dezimalkomma oder Tausenderpunkt ("1.234,56", "1,234.56") |
"integer" |
eine ganze Zahl; Nachkommastellen werden abgewiesen (siehe unten) |
"boolean" |
true / false |
"array" |
Liste; bei kc:childTable siehe Detail-Tabellen |
Wie lang ein Text sein darf¶
| Schlüssel | Wirkung |
|---|---|
kc:maxLength |
höchstens so viele Zeichen — bestimmt auch die Spaltenbreite (siehe unten) |
kc:minLength |
mindestens so viele Zeichen (leere, nicht-pflichtige Felder sind erlaubt) |
Feste Auswahl: nur bestimmte Werte (enum)¶
Ein Feld lässt sich auf eine geschlossene Werteliste einschränken. Werte außerhalb der Liste lehnt der Server ab. Im Schema sind das drei Zeilen:
Für Auswahllisten mit lesbarem Anzeigetext siehe Lookups.
Datum und Uhrzeit¶
Datumsfelder prüft KCForms streng — Muster und Kalender:
| Format | Muster | Beispiel für einen Fehler |
|---|---|---|
date |
JJJJ-MM-TT |
2026-02-30 |
date-time |
JJJJ-MM-TT HH:mm (auch mit T, Sekunden, Zeitzone) |
2026-13-01 10:00 |
Gespeichert wird immer im ISO-Format; die Anzeige steuert
kc:dateFormat bzw. kc:formDateFormat. Der Datums-Picker kennt
Mindest- und Höchstdatum (kc:minDate, kc:maxDate), Kalenderwochen und
weitere Optionen.
format: "email" erzeugt ein E-Mail-Eingabefeld, prüft auf dem Server
aber nicht streng — für strenge Prüfung ein pattern ergänzen.
Zwei Datumsfelder vergleichen¶
Ein Datumsfeld kannst du gegen andere Datumsfelder prüfen lassen — der klassische Fall ist „Ende nicht vor Beginn". Am späteren Feld legst du dazu eine oder mehrere Vergleichsregeln an, jede mit eigener Fehlermeldung.
Hinter den Kulissen: Datumsvergleich (kc:dateCompare)
"reiseende": {
"type": "string", "format": "date", "title": "Reiseende",
"kc:dateCompare": {
"enabled": true,
"rules": [
{ "op": "ge", "other": "reisebeginn", "message": "Das Ende darf nicht vor dem Beginn liegen." }
]
}
}
op: lt (vor), le (vor oder gleich), gt (nach), ge (nach oder
gleich), eq, ne. Mehrere Regeln sind möglich.
Eingaben gegen ein Muster prüfen¶
Muss ein Wert einer festen Form folgen — fünfstellige PLZ, Aktenzeichen, IBAN-Schreibweise —, hinterlegst du am Feld ein Muster: einen regulären Ausdruck, dazu die Fehlermeldung, die der Anwender zu sehen bekommt, und ob das ganze Feld passen oder das Muster nur enthalten sein muss.
Hinter den Kulissen: Muster am Beispiel einer IBAN
"iban": {
"type": "string", "title": "IBAN",
"pattern": "^[A-Z]{2}\\d{2}[A-Z0-9]+$",
"kc:patternMode": "match",
"kc:patternMessage": "Bitte gültige IBAN eintragen."
}
JSON-Schema kennt pattern als regulären Ausdruck; KCForms ergänzt Modus
und Fehlertext.
| Schlüssel | Wert | Bedeutung |
|---|---|---|
pattern |
regulärer Ausdruck (Java-Syntax) | das Muster |
kc:patternMode |
"match" (Standard) |
das ganze Feld muss passen |
"contain" |
das Feld muss das Muster enthalten | |
kc:patternMessage |
Text | Fehlermeldung unter dem Feld |
Muster werden live beim Verlassen und beim Speichern geprüft. Ein leeres, nicht-pflichtiges Feld scheitert nie am Muster.
Zwei weitere typische Fälle: eine PLZ, die vollständig aus fünf Ziffern
bestehen muss (match), und eine Telefonnummer, in der irgendwo mindestens
drei Ziffern vorkommen müssen (contain).
Hinter den Kulissen: PLZ (match) und Telefon (contain)
Fertige Prüfungen
Für IBAN, BIC, USt-IdNr. und Ähnliches gibt es Feld-Validatoren mit echter Prüfziffer-Kontrolle — ein Muster prüft nur die Form.
Nachkommastellen bei Zahlen (kc:decimals)¶
Die Nachkommastellen eines Zahlenfeldes legen zweierlei fest: wie der Wert
angezeigt wird und wie genau die Datenbank-Spalte (DECIMAL(18, n)) ihn
aufbewahrt. Im Schema ist das ein einzelner Schlüssel:
kc:decimals |
Spalte | Anzeige |
|---|---|---|
0 |
DECIMAL(18, 0) |
1234 |
2 |
DECIMAL(18, 2) |
1.234,56 |
| (fehlt) | DECIMAL(18, 4) |
wie eingegeben |
Erlaubt sind 0 bis 10. Beim Verlassen des Feldes formatiert das Formular
den Wert mit der gewählten Anzahl Nachkommastellen. Tausender- und
Dezimaltrenner, Präfix und Suffix steuern kc:thousandSeparator,
kc:decimalSeparator, kc:numberPrefix und kc:numberSuffix.
Bei Berechnungsfeldern genügt eine Angabe¶
Auch der Formel-Editor eines Berechnungsfeldes fragt nach Nachkommastellen. Du musst die Zahl nur an einer der beiden Stellen eintragen — steht am Feld selbst keine, gilt die aus der Formel. Steht sie an beiden, gewinnt die Angabe am Feld: sie beschreibt die Anzeige, die Formel-Angabe zuerst die Rechengenauigkeit.
Ist nirgends eine Angabe hinterlegt, zeigt das Formular so viele Stellen, wie
der Wert selbst mitbringt — ein gespeicherter Betrag 238,50 erscheint also
als 238,50 und nicht als 238,5. Im Ausdruck gelten in diesem Fall zwei
Stellen; wer beides sicher gleich haben will, trägt die Nachkommastellen
ausdrücklich ein.
Zahlenbereich (minimum / maximum)¶
Bei einem Zahlenfeld kannst du im Reiter Element ein Minimum und ein
Maximum eintragen. Beide Grenzen sind einschließend: Bei 0 bis 100
sind 0 und 100 erlaubt, −1 und 100,01 nicht.
"prozent": { "type": "number", "title": "Anteil (%)",
"kc:decimals": 2, "minimum": 0, "maximum": 100 }
Der erlaubte Bereich steht als Hinweis unter dem Feld („Erlaubt: 0 bis 100“) — der Anwender muss also nicht erst dagegenlaufen, um ihn zu erfahren. Trägst du nur eine der beiden Grenzen ein, nennt der Hinweis nur diese („Erlaubt: mindestens 18“). Geprüft wird beim Verlassen des Feldes und beim Speichern; ein Verstoß markiert das Feld rot und blockiert das Speichern wie jeder andere fachliche Fehler. Ein Entwurf lässt sich trotzdem zwischenspeichern, falls das Formular das erlaubt — der Wert passt ja in die Spalte, er gefällt nur nicht.
Vor dem Stand vom 05.10.2026 hatten diese beiden Felder keine Wirkung
Der Dialog schrieb minimum und maximum seit je ins Schema, und gelesen
hat sie niemand: weder die Prüfung auf dem Server noch das Formular. Wer
sie in einem älteren Formular eingetragen hat, bekommt sie jetzt
nachträglich scharf. Schau bei Bestandsformularen also einmal nach, ob
die dort hinterlegten Grenzen noch stimmen — sonst beanstandet das
Formular plötzlich Eingaben, die es jahrelang angenommen hat.
Ganzzahlfelder nehmen keine Nachkommastellen¶
Ein Feld vom Typ integer liegt in einer Ganzzahl-Spalte. Trägt jemand dort
5,7 ein, meldet das Feld „Bitte eine ganze Zahl ohne Nachkommastellen
eingeben". 5 und 5,0 gehen durch — 5,0 ist eine ganze Zahl, auch wenn
sie eine Null hinter dem Komma hingeschrieben bekommen hat.
Der Fehler ist hart und blockiert das Speichern auch im Entwurfsmodus. Das ist Absicht: Die Alternativen wären, den Wert beim Speichern stillschweigend zu runden — dann stünde eine andere Zahl im Datensatz als die eingegebene — oder ihn fallen zu lassen. Beides ist schlechter als ein Hinweis, den man in zwei Sekunden abstellt.
Vor dem Stand vom 05.10.2026 ging der Wert verloren
5,7 galt bis dahin als gültige Zahl. Das Speichern meldete Erfolg, und in
der Spalte stand nichts — kein Hinweis, kein Eintrag im Protokoll.
Dasselbe passierte bei 1.000,50 in einem Zahlenfeld mit
Nachkommastellen, also einem Betrag mit deutschem Tausenderpunkt. Beides
kommt jetzt an bzw. wird gemeldet. Wenn in einem Bestandsformular
Zahlenfelder unerklärlich leer sind, ist das die wahrscheinliche Ursache.
Die technische Obergrenze¶
Unabhängig von minimum/maximum fasst die Spalte nur eine begrenzte Zahl.
Wie viel, hängt an den Nachkommastellen
ab: Beide teilen sich einen Vorrat von 18 Stellen.
| Nachkommastellen | Stellen vor dem Komma | größter Wert |
|---|---|---|
0 |
18 | 999999999999999999 |
2 |
16 | 9999999999999999,99 |
4 (Vorgabe) |
14 | 99999999999999,9999 |
Ganzzahl (integer) |
19 | 9223372036854775807 |
Wird diese Grenze überschritten, meldet das Feld „Die Zahl ist zu groß — höchstens 14 Stellen vor dem Komma (aktuell 15)“. Dieser Fehler ist hart: Er blockiert das Speichern auch im Entwurfsmodus, weil die Zahl physikalisch nicht in die Spalte passt. Diese Grenze steht bewusst nicht als Hinweis unter dem Feld — sie liegt so hoch, dass niemand sie im Alltag berührt, und würde unter jedem Zahlenfeld nur Störung sein.
Die beiden Richtungen verhalten sich verschieden
Zu viele Stellen nach dem Komma werden gerundet — aus 1,23456789
wird in einem Feld mit vier Stellen 1,2346, ohne Meldung. Zu viele
Stellen vor dem Komma werden abgewiesen. Der Grund ist, dass Runden
eine Entscheidung ist, die man treffen kann, ohne den Anwender zu fragen;
das Weglassen einer Führungsstelle wäre dagegen eine andere Zahl.
Vorsicht beim Grenzfall: Das Runden kann den Überlauf selbst erzeugen.
99999999999999,99995 hat 14 Stellen vor dem Komma und ist damit
scheinbar in Ordnung — gerundet auf vier Nachkommastellen werden daraus
100000000000000,0000, also 15. Das Formular rechnet das mit und
beanstandet die Eingabe.
Mehrfachauswahl: wie viel passt hinein?¶
Die Werte einer Mehrfachauswahl — Ankreuzgruppe, Mehrfach-Auswahlliste oder
freie Stichwortliste — liegen zusammen als Liste in einer Spalte. Wie viel
dort hineinpasst, zeigt die Kopfzeile des Feld-Dialogs
an: Typ: multicheck / string(500).
Wird mehr gewählt, als hineinpasst, meldet das Feld „Die Auswahl ist zu umfangreich — sie braucht 1.161 Zeichen, das Feld fasst 500". Der Fehler ist hart und blockiert das Speichern auch im Entwurfsmodus, weil die Auswahl physisch nicht in die Spalte passt.
Wie viel Platz entsteht, hängt davon ab, was das Feld weiß:
| Feld | Platz |
|---|---|
| Feste Optionsliste | so viel, wie alle Optionen zusammen brauchen — mindestens 500 Zeichen |
| Freie Stichwortliste | 500 Zeichen |
Mit eigener Höchstlänge (kc:maxLength) |
genau diese — ab 4000 wird daraus unbegrenzter Text |
Bei einer festen Optionsliste kann der Platz also gar nicht ausgehen: Er ist so bemessen, dass alle Optionen gleichzeitig angehakt sein dürfen. Eng wird es nur bei frei eingetippten Stichworten. Brauchst du dort mehr, trage im Reiter Erweitert eine Höchstlänge ein.
Vor dem Stand vom 06.10.2026 gab es hier keine Prüfung
Eine zu große Auswahl lief ungebremst in die Datenbank und kam als technischer Abbruch zurück, nicht als Feldfehler. Gespeichert wurde nichts.
Was in einer Detail-Tabelle geprüft wird¶
Seit dem Stand vom 07.10.2026 prüft der Server jede Zelle einer Detail-Tabelle so wie ein gewöhnliches Feld: Typ, Länge, Zahlenbereich und Datumsform. Die Meldung nennt Zeile und Spalte:
Zeile 2, „Datum“: Bitte ein gültiges Datum eingeben (TT.MM.JJJJ)
Die Grenzen stammen aus der Spalte dieser Zelle — die ist eigenständig und etwas schmaler bemessen als die eines Hauptfeldes. Ohne eigene Angabe fasst eine Textspalte in einer Detail-Tabelle 255 Zeichen.
Diese Befunde sind hart: Sie blockieren das Speichern auch im Entwurfsmodus, weil der Wert sonst physisch nicht in die Spalte passt.
Vor dem Stand vom 07.10.2026 gab es diese Prüfung nicht
Dieselbe Eingabe verhielt sich im Hauptformular und in einer Tabellenzelle völlig verschieden:
| Eingabe | Hauptfeld | Detail-Zelle (vorher) |
|---|---|---|
Datum 32.12.2012 |
abgelehnt | still als 2032-12-20 gespeichert |
Datum morgen |
abgelehnt | technischer Abbruch |
Zahl viel |
abgelehnt | gespeichert — Zelle blieb leer |
| 600 Zeichen in einer 255er-Spalte | abgelehnt | technischer Abbruch |
Der erste Fall war der tückischste: Aus einem Datum, das es nicht gibt, wurde ein anderes, plausibel aussehendes. Wenn in älteren Datensätzen Detail-Zellen unerklärlich leer sind oder ein Datum nicht zur Eingabe passt, ist das die wahrscheinliche Ursache.
Nicht geprüft werden in Zellen enum und Muster (kc:pattern). Das sind
fachliche Regeln und keine Speichergrenzen — sie können nichts zerstören.
Textlänge und Spaltenbreite (kc:maxLength)¶
Die zulässige Textlänge bestimmt zugleich, wie breit die Spalte in der Datenbank angelegt wird:
kc:maxLength |
Spalte |
|---|---|
| (fehlt) | VARCHAR(255) |
| bis 4 000 | VARCHAR(n) |
| über 4 000 | TEXT |
Textbereiche (kc:widget: "textarea") werden immer als TEXT gespeichert.
Eine spätere Erhöhung verbreitert eine bestehende Spalte nicht
automatisch — siehe Datenmodell.
Die Grenze greift schon beim Tippen
Das Feld nimmt nicht mehr als kc:maxLength Zeichen an — beim Tippen wie
beim Einfügen, ein- und mehrzeilig und auch in Detail-Tabellen. Vorher ließ
sich beliebig viel eingeben und der Hinweis kam erst beim Speichern; bei
einem versehentlich eingefügten Roman war das eine unangenehme Überraschung.
Damit niemand rätselt, warum das Feld plötzlich nichts mehr annimmt, blendet
sich ab 90 % der Grenze automatisch der Zeichenzähler ein („487 / 500"), auch
ohne kc:showCharCounter — er wird gelb und bei Erreichen der Grenze rot.
Bestehende Daten bleiben unangetastet: Ein Datensatz, der die Grenze schon überschreitet (weil sie später gesenkt wurde), wird weiterhin vollständig angezeigt und nicht stillschweigend gekürzt. Beim Speichern meldet ihn die Validierung wie bisher.
Auch ohne kc:maxLength ist die Spalte begrenzt
Das ist die häufigere Stolperfalle: Ein gewöhnliches Textfeld ohne
kc:maxLength bekommt VARCHAR(255), ein format: "email" sogar nur
VARCHAR(120), und eine Auswahlliste richtet sich nach ihrem längsten
Eintrag. Wer dort mehr hineinschreibt, bekam früher keine Feldmeldung,
sondern die Meldung des Datenbanktreibers („Data too long for column")
als technischen Fehler.
Die Validierung prüft deshalb gegen die tatsächliche Kapazität der
Spalte — auch dann, wenn im Schema gar keine Länge steht. Wer mehr Platz
braucht, setzt kc:maxLength ausdrücklich; über 4 000 entsteht ohnehin
TEXT und die Zeichenzahl ist dann praktisch offen.
Die Prüfung läuft ein zweites Mal nach den Skripten, unmittelbar vor
dem Schreiben. Ein onValidate- oder onBeforeSave-Hook, der selbst einen
zu langen Wert setzt, wird also ebenfalls abgefangen — mit Feldnamen statt
Stacktrace. Nicht abgedeckt ist bewusst rohes db.update(...) aus einem
Skript: das ist die SQL des Autors, dort gehört die Treibermeldung hin.
Was als ein Zeichen zählt¶
Gezählt wird seit dem Stand vom 07.10.2026 so, wie die Datenbank zählt: in Zeichen (Unicode-Codepunkten), nicht in internen Speichereinheiten. Ein Emoji ist damit ein Zeichen — in ein Feld mit Höchstlänge 10 passen zehn davon.
Vorher zählten Emoji doppelt
Bis dahin meldete ein Feld mit Höchstlänge 300 bei 300 Emoji „Höchstens 300 Zeichen erlaubt (aktuell 600)“ — obwohl die Spalte genau diese 300 aufgenommen hätte. Das Feld hielt für solche Zeichen also die halbe zugesagte Menge, und die genannte Zahl stand auf keinem Bildschirm. Für gewöhnlichen Text ändert sich nichts: Dort waren beide Zählweisen immer gleich.
Wo die Zählung trotzdem von der Anschauung abweicht
Manche Emoji bestehen aus mehreren Zeichen, die zu einem Bild zusammengesetzt werden — die Familie zählt fünf. Das ist kein Versehen: Maßgeblich ist, was die Spalte zählt, und die zählt ebenfalls fünf. Würde das Formular hier anders rechnen als die Datenbank, wäre wieder eine der beiden Zahlen falsch.
Eigene Regeln im Skript (onValidate)¶
Was das Schema nicht ausdrücken kann, gehört ins Skript — typisch feldübergreifende Regeln:
// onValidate
if (kc.num(ctx.form.rabattProzent) > 0 && kc.isEmpty(ctx.form.kommentar)) {
ctx.addError('kommentar', 'Bei Rabatt > 0 ist eine Begründung erforderlich.');
}
// Bestelldatum nicht in der Zukunft
var heute = new Date().format('yyyy-MM-dd');
if (ctx.form.bestelldatum && ctx.form.bestelldatum > heute) {
ctx.addError('bestelldatum', 'Das Bestelldatum darf nicht in der Zukunft liegen.');
}
ctx.addError(feld, text) sammelt Fehler; das Formular zeigt sie am
jeweiligen Feld und im Fehler-Banner. Mehr zu den Skript-Hooks:
Lifecycle.
Speichern trotz Fehlern¶
Zwei Schalter in den Formular-Eigenschaften → Erweiterte Einstellungen:
| Schalter | Wirkung |
|---|---|
Speichern mit Fehlern erlauben (allowSaveWithErrors) |
der Datensatz wird trotz Prüffehlern gespeichert — für Entwürfe |
Absenden mit Fehlern erlauben (allowSubmitWithErrors) |
zusätzlich läuft onSubmit (Mails, Folgeaktionen) trotz Fehlern; nur zusammen mit dem ersten Schalter sinnvoll |
Was der Anwender von einem Fehler mitbekommt¶
Schlägt das Speichern an einer Prüfung fehl, passieren drei Dinge:
- Oben erscheint eine Meldung mit der Anzahl der offenen Felder und dem ersten davon im Klartext — dort, wo auch der Speichern-Knopf sitzt. Bei einem langen Formular sähe man einen Hinweis am Fuß nämlich nie, und der Klick würde folgenlos wirken.
- Die Maske springt zum ersten betroffenen Feld und setzt den Schreibcursor hinein. Liegt es auf einer anderen Seite eines mehrseitigen Formulars, wechselt die Ansicht mit.
- Jedes betroffene Feld wird rot markiert — Rahmen bei Text-, Zahl-, Datums-, Auswahl- und Währungsfeldern, ein roter Ring bei Ankreuzfeldern (die malt der Browser selbst, ein Rahmen wäre dort unsichtbar). Darunter steht die Begründung.
Ein einmal gemeldeter Pflicht-Hinweis bleibt stehen, solange das Feld leer ist. Ihn kurz anzuklicken oder etwas zu tippen und wieder zu löschen lässt ihn also nicht verschwinden — er geht erst, wenn wirklich etwas drinsteht.
Zwei Extras für den Formular-Designer
Mit kc:showErrorsProminently bekommst du zusätzlich ein aufklappbares
Fehler-Verzeichnis oben im Formular, durch das man klicken kann; mit
kc:showSubmitErrorModal einen Dialog beim Speichern. Beide sind
optional — Meldung, Sprung und rote Markierung gibt es immer.
Wo geprüft wird¶
Alle Prüfungen laufen am Ende auf dem Server — auch die, die schon im Browser gemeldet werden. Sie lassen sich also nicht dadurch umgehen, dass jemand das Formular anders bedient als vorgesehen. Intern sortiert KCForms die Prüfungen in drei Schichten und ruft je nach Auslöser — Knopf Validieren, Speichern oder Verlassen eines Feldes — unterschiedlich viel davon auf.
Hinter den Kulissen: die drei Prüf-Schichten und ihre Auslöser
Validierung passiert in KCForms in drei Schichten:
- Schema-Prüfung (Server) — automatisch aus dem Schema: Pflicht,
Typ, Länge, Zahlenbereich, Auswahlwerte, Muster, Datumsformat,
Datumsvergleich.
Berücksichtigt
kc:visibleIfundkc:requiredIf. onValidate-Skript — eigene Geschäftsregeln, die das Schema nicht ausdrücken kann.- Feld-Validatoren (
kc:validator) — freigegebene Prüffunktionen aus Bibliotheken (IBAN, USt-IdNr. …), live im Browser und verbindlich auf dem Server.
Dazu kommen Live-Prüfungen beim Verlassen eines Feldes — ohne Pflicht-Check, sonst wäre jedes noch leere Feld sofort rot.
Weil diese Prüfung Pflichtfehler gar nicht kennt, darf sie einen bereits gemeldeten auch nicht löschen: Ein Pflicht-Hinweis überlebt das Verlassen des Feldes, solange es leer bleibt. Sonst hätte ein Klick ins Feld gereicht, um die Markierung loszuwerden — und das Speichern wäre danach trotzdem fehlgeschlagen.
Welcher Auslöser welchen Endpunkt anspricht:
| Auslöser | Endpunkt | Was wird geprüft? |
|---|---|---|
| Knopf Validieren | POST /api/forms/{id}/validate |
Schema-Prüfung (inkl. Pflicht), onValidate, Feld-Validatoren |
| Speichern | POST /api/forms/{id}/submit |
dasselbe, danach Speichern (siehe Reihenfolge) |
| Feld verlassen | POST /api/forms/{id}/fieldChange |
Schema-Prüfung nur dieses Feldes, ohne Pflicht-Check; läuft zusammen mit onFieldChange |
Feld verlassen mit kc:serverValidateOnChange: true |
POST /api/forms/{id}/validate |
vollständige Prüfung inkl. onValidate; Fehler erscheinen direkt am Feld |
Reihenfolge beim Speichern¶
flowchart TB
A["Speichern"] --> B["1 · Schema-Prüfung<br/>Pflicht, Typ, Länge, Zahlenbereich,<br/>enum, Muster, Datum, Datumsvergleich"]
B --> C["2 · onValidate-Skript"]
C --> D["3 · Feld-Validatoren (kc:validator)"]
D --> E{"Fehler?"}
E -- "ja (und Speichern mit Fehlern aus)" --> F["Antwort mit Fehlern"]
E -- "nein" --> G["4 · onBeforeSave<br/>(kann abbrechen)"]
G --> H["5 · Speichern<br/>form_<id> + Detail-Tabellen"]
H --> I["6 · onSubmit<br/>Mail, PDF, Dateien"]
I --> J["7 · onAfterSave"]
J --> K["Antwort an das Formular"]
Der Knopf Validieren führt nur die Schritte 1–3 aus — ohne Speichern
und ohne onSubmit.
Stolperfallen¶
format: "date"mitpattern: "dd.MM.yyyy"scheitert: Gespeichert und geprüft wird ISO (JJJJ-MM-TT). Das Anzeigeformat steuertkc:dateFormat.- Backslashes in JSON verdoppeln:
\dschreibt man\\d. - Feldübergreifende Regeln kann das Schema nicht ausdrücken — dafür
gibt es
kc:requiredIf,kc:dateCompareundonValidate. - Pflicht über eine
@Regel: Die Server-Prüfung löst@Regelnnicht auf, siehe Regeln. - Prüfung findet zu wenig? Unter System-Administration → Betrieb &
Überwachung → Log-Konfiguration den Logger
com.kcforms.formsaufDEBUGstellen — ohne Neustart.