Direkt zum Hauptinhalt

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​

FeldTypPflichtHinweise
logicalNamestringjaMit Herausgeberpräfix, Snake-Case in Kleinbuchstaben.
displayNamestringjaLesbarer Formularname.
entitystringjaDer logische Name der besitzenden Tabelle.
descriptionstringneinDie Zeile, die in der Titelleiste des Formulars unter dem Titel angezeigt wird.
iconstringneinDas Symbol in der Titelleiste des Formulars.
sectionsarrayeines von beidenEin oder mehrere Abschnitte mit Titel – das ältere, flache Layout (siehe unten).
tabsarrayeines von beidenDas umfangreichere Registerkarten-Layout (siehe unten).
actionsarrayneinGestaltbare 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)​

FeldTypPflichtHinweise
titlestringjaAbschnittsüberschrift.
columnsintegerjaLayoutspalten, 1–4.
fieldsarrayjaFeldplatzierungen (siehe unten).

Registerkarte (tabs-Layout)​

FeldTypPflichtHinweise
idstringneinStabile Designer-ID.
titlestringjaTitel der Registerkarte.
iconstringneinSymbol neben dem Titel der Registerkarte.
rowsarrayjaLayoutzeilen in voller Breite: { id?, columns: 1–4, sections: [...] }, jeder Abschnitt { id?, title, icon?, span?, fields, timeline? }.

Feldplatzierung​

FeldTypPflichtHinweise
fieldstringsiehe HinweiseDer 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.
labelstringneinÜberschreibt die Beschriftung; fehlt sie, wird der Anzeigename des Felds verwendet.
controlstringneinDer 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.
controlTypestringneinDas 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.
requiredbooleanneinOb 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.
readOnlybooleanneinOb 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.
controlPropsobjectneinDie 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)​

FeldTypGelesen vonHinweise
dateFormatstringDate, 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.
trueLabelstringCheck, ToggleDie Beschriftung für den Zustand „Ja“.
falseLabelstringCheck, ToggleDie Beschriftung für den Zustand „Nein“.
rowsintegerTextAreaAnzahl sichtbarer Zeilen, 2–20.
lookupEntitystringLookupLogischer Name der Tabelle, gegen die das Nachschlagefeld auflöst.
lookupViewstringLookupLogischer 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.
lookupRowCountintegerLookupWie 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.
lookupPrimaryFieldstringLookupÜ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.
lookupSecondaryFieldstringLookupÜ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.
lookupImageFieldstringLookupÜ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.
imageSizestringBildfeldWie groß die Vorschau eines Bildfelds gerendert wird – sm (Standard, Avatargröße), md oder lg (ein prominentes Bild). Nur für ein Bildfeld von Bedeutung.
labelTextstringLabelDer 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.
optionsarrayDropdownFeste 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.

FeldTypPflichtHinweise
sourcesarray (1–10)jaDie Tabellen, die sie liest, je ein Eintrag (siehe unten).
pageSizeinteger (5–100)neinAngezeigte Elemente vor Mehr laden; 20, wenn nicht angegeben.

Jede Quelle:

FeldTypPflichtHinweise
entitystringjaDer logische Name der Quelltabelle.
regardingstringjaEin 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.
datestringjaEin Datums-/Uhrzeitfeld der Quelle (einschließlich Systemfeldern wie created_at_utc). Die Elemente werden danach sortiert, die neuesten zuerst.
titlestringjaDas Feld, das die Überschrift jedes Elements bildet.
bodystringneinEin Feld, dessen Anfangsworte jedes Element anzeigt.
typestringneinEin 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.
statusstringneinEin 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" }
]
}
]
}
]
}
]
}