Definition eines modellgesteuerten Formulars
Schema-ID: model-driven-form@2
Abgelöste Version: model-driven-form@1
(model-driven-form-v1.schema.json) bleibt
veröffentlicht und registriert, sodass eine bereits bereitgestellte Lösung weiterhin gegen das
Schema validiert wird, für das sie erstellt wurde. Version 2 ergänzt lediglich das optionale
controlProps.lookupView, daher ist jede v1-Definition auch eine gültige v2-Definition.
Maschinenlesbares Schema: model-driven-form.schema.json
Die maßgebliche Darstellung eines Formulars modellgesteuerter Apps (Abschnitt 6.7) – des Layouts, mit dem ein einzelner Datensatz angezeigt und bearbeitet wird. Es wird identisch validiert, ob es aus dem Designer, einem API-Aufruf, einem KI-Assistenten oder einem Lösungsimport stammt.
Aufbau
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
logicalName | string | ja | Mit Herausgeberpräfix, Snake-Case in Kleinbuchstaben. |
displayName | string | ja | Lesbarer Formularname. |
entity | string | ja | Der logische Name der besitzenden Tabelle. |
description | string | nein | Die Zeile, die in der Titelleiste des Formulars unter dem Titel angezeigt wird. |
icon | string | nein | Das Symbol in der Titelleiste des Formulars. |
sections | array | eines von beiden | Ein oder mehrere Abschnitte mit Titel – das ältere, flache Layout (siehe unten). |
tabs | array | eines von beiden | Das umfangreichere Registerkarten-Layout (siehe unten). |
actions | array | nein | Gestaltbare Aktionen der Befehlsleiste. |
Ein Formular enthält entweder sections oder tabs, nicht keines von beiden. Neue
Definitionen sollten tabs verwenden; sections wird akzeptiert, damit bestehende Formulare
weiter funktionieren, und wie eine Registerkarte mit einspaltigen Zeilen behandelt.
Abschnitt (älteres sections-Layout)
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
title | string | ja | Abschnittsüberschrift. |
columns | integer | ja | Layoutspalten, 1–4. |
fields | array | ja | Feldplatzierungen (siehe unten). |
Registerkarte (tabs-Layout)
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
id | string | nein | Stabile Designer-ID. |
title | string | ja | Titel der Registerkarte. |
icon | string | nein | Symbol neben dem Titel der Registerkarte. |
rows | array | ja | Layoutzeilen in voller Breite: { id?, columns: 1–4, sections: [...] }, jeder Abschnitt { id?, title, icon?, span?, fields, timeline? }. |
Feldplatzierung
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
field | string | siehe Hinweise | Der logische Name des Felds (muss auf der Tabelle definiert sein). Nur bei einer Label-Platzierung weggelassen, die statischer Inhalt ist und an kein Feld gebunden wird. |
label | string | nein | Überschreibt die Beschriftung; fehlt sie, wird der Anzeigename des Felds verwendet. |
control | string | nein | Der logische Name eines benutzerdefinierten Steuerelements, das anstelle des nativen Feldeditors eingehängt wird. Das Steuerelement muss in der Umgebung installiert sein; ist es das nicht, greift das Feld auf seinen nativen Editor zurück. |
controlType | string | nein | Das eingebaute Steuerelement, mit dem das Feld gerendert wird (Abschnitt 6.13.5). Einer von Text, TextArea, Check, Toggle, Date, DateTime, Time, PersianDate, PersianDateTime, PersianTime, Lookup, Dropdown, Label. Weglassen, damit der Player das Standardeingabeelement für den Datentyp des Felds wählt. Die Persian…-Varianten rendern dieselbe Auswahl wie ihre gregorianischen Gegenstücke, öffnen sich aber unabhängig von der App-Sprache im Jalali-Kalender; der gespeicherte Wert ist weiterhin ein gregorianischer Zeitpunkt. Label ist statischer Markdown-Inhalt (controlProps.labelText) ohne gebundenes Feld. |
required | boolean | nein | Ob das Feld auf diesem Formular geschäftlich erforderlich ist (Abschnitt 6.13.5) – der Benutzer muss es vor dem Speichern ausfüllen. Eine Angelegenheit des Formulars, keine Datenbankeinschränkung (jede Tabellenspalte ist nullable); der Player setzt es im Browser durch, der Server nicht. Fehlt die Angabe, gilt das eigene IsRequired des Felds. |
readOnly | boolean | nein | Ob das Feld auf diesem Formular schreibgeschützt angezeigt wird (Anzeige, keine Bearbeitung). Ein schreibgeschütztes Feld wird als einfacher Text ohne Eingabesteuerelement gerendert. Fehlend ist nicht false: Fehlt die Angabe, ist das Feld auf einem Register bearbeitbar, im header aber schreibgeschützt; ein Kopfzeilenfeld wird also mit einem ausdrücklichen false bearbeitbar. |
controlProps | object | nein | Die Eigenschaften des gewählten Steuerelements (siehe unten). |
Vorrang der Steuerelemente: Ein benutzerdefiniertes control hat Vorrang vor controlType,
das wiederum Vorrang vor dem Standard des Felddatentyps hat. Lassen Sie beide weg, wählt der
Player den Standard.
Erforderlich ist eine Formularregel, keine Spalteneinschränkung. required steht an der
Platzierung, sodass dasselbe Feld auf einem Formular erforderlich und auf einem anderen optional
sein kann, und es wird nur im Player geprüft, wenn der Benutzer speichert. Tabellenspalten sind auf
Datenbankebene immer nullable (wie in Power Apps), daher wird ein durch einen Import oder
API-Aufruf erstellter Datensatz nie wegen eines fehlenden erforderlichen Felds abgewiesen – der
einzige Wert, auf dem der Server besteht, ist das Primärfeld (Namensfeld) der Tabelle.
Steuerelementeigenschaften (controlProps)
| Feld | Typ | Gelesen von | Hinweise |
|---|---|---|---|
dateFormat | string | Date, DateTime, Time (und ihre Persian…-Varianten) | Anzeigeformat. Token: yyyy/yy, MMMM (voller Monatsname)/MMM (kurz)/MM/M, dd/d, HH, mm, ss; alle anderen Zeichen werden wörtlich übernommen. Fehlt die Angabe, gilt der Standard des Kalenders – d MMMM yyyy für Persisch (z. B. 12 اردیبهشت 1405), yyyy/MM/dd für Gregorianisch. |
trueLabel | string | Check, Toggle | Die Beschriftung für den Zustand „Ja“. |
falseLabel | string | Check, Toggle | Die Beschriftung für den Zustand „Nein“. |
rows | integer | TextArea | Anzahl sichtbarer Zeilen, 2–20. |
lookupEntity | string | Lookup | Logischer Name der Tabelle, gegen die das Nachschlagefeld auflöst. |
lookupView | string | Lookup | Logischer Name der Ansicht, die die im Ergebnisbereich des Nachschlagefelds angezeigten Spalten liefert. Fehlt die Angabe, löst die Plattform eine auf – siehe viewType im Ansichtsschema. |
lookupRowCount | integer | Lookup | Wie viele Kandidatenzeilen der Bereich des Nachschlagefelds auf einmal anbietet (1–500). Fehlt die Angabe, gilt der Plattformstandard von 10. Der Server begrenzt, was auch immer angefordert wird – eine Auswahl ist kein Bericht. Nach v2 durch Erweiterung an Ort und Stelle hinzugefügt: Jede Definition, die ohne diese Eigenschaft gültig war, bleibt gültig. |
lookupPrimaryField | string | Lookup | Überschreibt pro Steuerelement, welches Feld die Namenszeile jedes Kandidaten ist. Fehlt die Angabe, wird das eigene Primärfeld der Zieltabelle verwendet; ein Name, der kein Feld der Zieltabelle ist, wird ignoriert. |
lookupSecondaryField | string | Lookup | Überschreibt pro Steuerelement die zweite Zeile unter dem Namen und damit das Feld, das die Zieltabelle vorgibt. Fehlt die Angabe, gilt die Vorgabe der Tabelle. |
lookupImageField | string | Lookup | Überschreibt pro Steuerelement, welches Datei-/Bildfeld das Bild jedes Kandidaten ist, und damit das Datensatzbild der Zieltabelle. Fehlt die Angabe, wird das Bild der Tabelle verwendet; ein Feld, das kein Bildfeld ist, wird ignoriert. |
imageSize | string | Bildfeld | Wie groß die Vorschau eines Bildfelds gerendert wird – sm (Standard, Avatargröße), md oder lg (ein prominentes Bild). Nur für ein Bildfeld von Bedeutung. |
labelText | string | Label | Der feste Text eines Label-Steuerelements, gerendert als kleine, sichere Markdown-Teilmenge: Überschriften mit #/##/###, **bold**, *italic*, `code`, Listen mit - , Links [text](url) (nur http/https/mailto/relativ) sowie {color:name}…{/color} (ein zugelassener Farbname oder #hex). Rohes HTML wird niemals gerendert. |
options | array | Dropdown | Feste Optionen, jeweils { value, label }, die zu genau diesem einen Feld gehören. Verwenden Sie für alles, was über Felder oder Tabellen hinweg wiederverwendet wird, bevorzugt einen Optionssatz: Ein Satz ist eine gemeinsam genutzte, versionierte Komponente mit kollisionssicheren Werten, während diese Optionen eine private Liste auf einem Formular sind. Ein Feld mit dem Datentyp OptionSet ignoriert diese Eigenschaft und bezieht seine Werte aus seinem Satz. |
Eigenschaften, die für den gewählten controlType nicht gelten, werden ignoriert, nicht
abgewiesen – wer das Steuerelement eines Felds wechselt und wieder zurückwechselt, verliert
also seine Konfiguration nicht.
Jedes referenzierte field muss ein auf der Tabelle definiertes Feld sein – das wird beim
Speichern zusätzlich zur Schemavalidierung durchgesetzt.
Zeitachsenabschnitt (timeline)
Ein Abschnitt in einer Registerkarte kann statt einer Gruppe von Feldern eine Zeitachse sein:
die Datensätze anderer Tabellen, deren Nachschlagefeld auf den geöffneten Datensatz zeigt,
zusammengeführt und die neuesten zuerst – die E-Mails, Anrufe und Notizen eines Kunden in einer
Spalte. Ein Abschnitt ist das eine oder das andere: Ist timeline vorhanden, muss fields ein
leeres Array sein.
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
sources | array (1–10) | ja | Die Tabellen, die sie liest, je ein Eintrag (siehe unten). |
pageSize | integer (5–100) | nein | Angezeigte Elemente vor Mehr laden; 20, wenn nicht angegeben. |
Jede Quelle:
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
entity | string | ja | Der logische Name der Quelltabelle. |
regarding | string | ja | Ein Nachschlagefeld auf der Quelltabelle, das auf die Tabelle des Formulars zielt, oder ein Nachschlagefeld für mehrere Tabellen, das sie aufführt. Die Zeitachse zeigt die Zeilen, deren Wert der geöffnete Datensatz ist. |
date | string | ja | Ein Datums-/Uhrzeitfeld der Quelle (einschließlich Systemfeldern wie created_at_utc). Die Elemente werden danach sortiert, die neuesten zuerst. |
title | string | ja | Das Feld, das die Überschrift jedes Elements bildet. |
body | string | nein | Ein Feld, dessen Anfangsworte jedes Element anzeigt. |
type | string | nein | Ein Optionssatz-Feld, das die Zeilen der Quelle unterscheidet. Jedes Element übernimmt Symbol und Farbe von seiner Option, der Filter zeigt einen Chip pro Option, und Neu bietet einen vorausgefüllten Eintrag pro Option an. |
status | string | nein | Ein Feld, das neben dem Datum jedes Elements angezeigt wird. |
Beim Speichern und beim Import wird jeder Name gegen die Tabellen der Umgebung geprüft: Die
Quelltabelle muss existieren, regarding muss auf die Tabelle des Formulars zeigen können, date
muss ein Datum sein, type muss eine Auswahl (Choice) sein, und der Rest muss existieren. Eine
Zeitachse, die eine dieser Prüfungen nicht besteht, wird abgewiesen (modelapps.form.timeline_*),
statt leer gezeichnet zu werden. Wird ein Feld gelöscht, das eine Zeitachse verwendet, wird es aus
der Zeitachse entfernt: Ein optionaler Teil entfällt, und eine Quelle, die ihr regarding, date
oder title verliert, wird entfernt.
Beispiel
{
"logicalName": "par_invoice_main",
"displayName": "Main",
"entity": "par_invoice",
"description": "The invoice's main form",
"icon": "Receipt",
"tabs": [
{
"id": "tab-general",
"title": "General",
"rows": [
{
"id": "row-1",
"columns": 2,
"sections": [
{
"id": "sec-header",
"title": "Header",
"fields": [
{ "field": "par_name", "required": true },
{ "field": "par_total", "label": "Amount" },
{ "field": "par_number", "readOnly": true },
{
"field": "par_due",
"controlType": "Date",
"controlProps": { "dateFormat": "dd/MM/yyyy" }
},
{
"field": "par_paid",
"controlType": "Toggle",
"controlProps": { "trueLabel": "Paid", "falseLabel": "Unpaid" }
},
{ "field": "par_signature", "control": "par_signature_pad" }
]
}
]
}
]
}
]
}