variables
Im Bereich variables einer page werden alle Variablen definiert, die auf dieser Page zur Verfügung stehen.
Es gibt sowohl simple Variablen mit einem der Typen:
-
string -
number -
boolean -
date -
datetime -
array -
time
als auch komplexe Variablen mit einem der Typen:
-
entitySet -
entityInstance -
style
Simple Variablen
data:
variables:
<name>:
type: string | number | boolean
[value]: any
[events]: VariableEvent
[alias]: string
Der aliaswird im Falle von Inputvariablenbinding als Url-Parameter verwendet.
Kontext:
// schreiben
$.variables.<name> = 'Wert' | 4711 | false
// lesen
debug.log($.variables.<name>)
Besonderheiten bei date und datetime
-
Die Variablentypen
dateunddatetimestehen im JavaScript-Context als JavaScript-Date-Objekte zur Verfügung. -
Wenn der Wert einer solchen Variable geändert werden soll, kann entweder ein ISO-8601 konformer String oder ein Zeitstempel in Millisekunden oder ein JavaScript-Date-Objekt verwendet werden.
OData Variablen
data:
variables:
<name>:
type: entitySet | entityInstance
source: odata
entity: <EntityName>
attributes: Array von Feldnamen/NavigationProperty-Definitionen | '*'
[filter]: Binding | Filter-String
[orderBy]:
- column: Feldname
[desc]: true | false
[events]: VariableEvent
[customParams]:
params:
- key: <KEY oder BINDING>
value: <KEY oder BINDING>
Eine NavigationProperty kann bei attributes wie folgt angegeben werden:
# Variante 1: Alle Felder der NavigationProperty laden
attributes:
- dmsDocumentVersion: "*"
# Variante 2: Nur bestimmte Felder der NavigationProperty laden
attributes:
- dmsDocumentVersion:
- uuid
- fileName
Kontext:
// Beim Schreiben muss eine Eigenschaft der Entität geschrieben werden und nicht die Variable selbst
// entitySets haben keine schreibbaren Eigenschaften
$.variables.<name>.artnr = 'MUTTER M4';
$.variables.<name>.artgruppe = 4711;
// lesen
debug.log($.variables.<name>)
debug.log($.variables.<name>.artnr)
VariableEvent
...
[beforeValueChanged]: $script | $backend
[afterValueChanged]: $script | $backend
Variablen können je nach Typ an Inputs, Grids oder Dropdowns gebunden werden. Falls sich der Wert einer Variablen ändert, unabhängig ob durch eine Oberflächen-Interaktion oder durch ein Skript, werden alle abhängigen Variablen und Controls aktualisiert.
entitySet
Ein entitySet enthält selbst keine Daten, sondern beschreibt wie und welche Daten von der gebundenen Komponente geladen werden. Daher kann ein entitySet immer nur an eine einzige Komponente gebunden werden.
data:
variables:
artikelNr:
type: string
events:
afterValueChanged:
$script: | # JS
if ($.event.value) {
$.variables.Dab010Filter = `artnr eq '${$.event.value}'`; // Filter für Dab010Set setzen.
await $.variables.Dab010Set.$.load(); // Dab010Set neu laden
const bez1 = $.variables.Dab010Set.$.items()[0]?.bez1; // Den ersten Datensatz holen und "bez1" extrahieren.
$.debug.log("Bezeichnung 1 aus Dab010Set:", bez1);
}
Dab010Filter:
type: string
value: "false"
Dab010Set:
type: entitySet
source: odata
entity: Dab010
filter:
$bind: Dab010Filter
controls:
- controlType: inputContainer
controls:
- controlType: label
value: Artikel-Nr.
- controlType: input
type: text
value:
$bind: artikelNr
Funktionen des $-Unterobjekts:
-
items(): Gibt eine Liste der aktuell geladenen Datensätze zurück. -
size(): Gibt die Anzahl aller ladbaren Datensätze zurück. -
reload(): Initiiert ein erneutes Laden der Daten. -
load(): Initiiert das Laden der Daten. -
sortValue(): Gibt die aktuellen Sortierungseinstellungen zurück. -
filterValue(): Gibt die aktuellen Filtereinstellungen zurück. -
deselectIfNotAvailable(): (async)-
Voraussetzungen: Das EntitySet ist an ein
entityGridgebunden, dessenselected-Eigenschaft an eine Variable gebunden ist. Beim EntityGrid muss außerdem die EigenschaftkeepGridSelectionauftruegesetzt sein. -
Funktionsweise: Wenn ein ausgewählter Datensatz nicht mehr geladen ist (bspw. durch Scrollen, durch eine geänderte Sortierung oder durch eine geänderte Filterung), dann wird die Selektion aufgehoben. Dabei wird der
valueder gebundenenselected-Variable entfernt.
-
-
executeAction(actionFQN: string, body: Record<string, any>): Promise<any>: (async)-
Führt die angegebene OData Aktion des entitySets aus
-
-
executeFunction(functionFQN: string, body: Record<string, any>): Promise<any>: (async)-
Führt die angegebene OData Funktion des entitySets aus
-
entityInstance
Eine entityInstance enthält zum einen die Werte eines Datensatzes und zum anderen das Unterobjekt $ mit dem ein Datensatz geändert, gelöscht oder neu angelegt werden kann. Außerdem gibt die Eigenschaft state Auskunft über den Zustand der entityInstance - browse, edit oder insert.
data:
variables:
artikel:
type: entityInstance
source: odata
entity: Dab010
...
controls:
- controlType: button
label: Speichern
disabled:
$expr: $.variables.artikel.$.state !== 'browse' || !$.variables.artikel.$.hasChanged()
events:
click:
$script: |
await $.variables.artikel.$.save();
notify.success('Der Artikel wurde gespeichert');
Darüber hinaus kann bei der Variablendefinition editMode mit angegeben werden. Zulässige Werte sind hier:
-
explicit: Eine instance Variable kann nur imeditState, d.h. nach explizitem Aufruf deredit()Funktion (siehe unten) modifiziert werden. Ein Modifizieren einer entity instance führt dann stattdessen zu einem Log in der Konsole. -
implicit: Die instance Variable kann auch imbrowseState modifizert werden und wechselt dann automatisch in deneditModus.
Standardmäßig wird der explizite Editmodus verwendet.
Funktionen des $-Unterobjekts:
-
edit(): (async) Versetzt die EntityInstance in den Edit-Modus. Danach darf diese bearbeitet werden. -
new(): (async) Versetzt die EntityInstance in den Insert-Modus. Danach darf diese bearbeitet werden. -
save(): (async) Speichert die aktuell in der EntityInstance gehaltenen Daten. -
delete(): (async) Löscht den aktuell ausgewählten Datensatz. -
reload(): (async) Fetcht die Entität aus dem Backend neu (kann nur inbrowseaufgerufen werden) -
cancel(): (async) Wenn die EntityInstance im Edit-/Insert-Modus ist, kann hiermit zurück in den Browse-Modus gewechselt werden, ohne dass Änderungen gespeichert werden. -
hasChanged(): gibt Auskunft darüber, ob die Werte einer EntityInstance geändert wurden. Nur im Edit-Modus verwendbar. -
executeAction(actionFQN: string, body: Record<string, any>): Promise<any>: (async)-
Führt die angegebene OData Aktion der entityInstance aus
-
-
executeFunction(functionFQN: string, body: Record<string, any>): Promise<any>: (async)-
Führt die angegebene OData Funktion der entityInstance aus
-
Style
Eine Style Variable kann einen statischen Style definieren. Dieser (oder einzelne Eigenschaften des Styles) kann dann an GUI Elemente statt der dortigen Styleeinstellungen gebunden werden.
some_style:
type: style
value:
font-size: 2.5rem
color: "purple:accent5"
background-color: "warning"
height: 30px
width: 30px
border:
color: "green"
Als Farben sind hierbei entweder die Status-Farben success, warning, danger, info zugelassen oder eine beSkinColor Farbe zugelassen.
Obwohl ein Ausdruck der form some_style.font-size kein valider JS Ausdruck ist muss diese Form bein binden von Attributen an Controls verwendet werden. Beim Zugriff innerhalb von dynamischem Javascript Code muss allerdings beim Zugriff auf js-invalider Properties (font-size & background-color) die Form mit bracket operator verwendet werden: $.variables.some_style["font-size"]
Besonderheit:
Style Variablen können außerdem in der be_package.install.yaml definiert werden und stehen so als Style Variablen im kompletten package zur Verfügung. Diese sind dort als Liste anzugeben, ber der der Variablenname als name Eigenschaft an das Object gehängt wird:
objects:
styles:
- name: some_style
value:
font-size: 2.5rem
Alternativ können diese styles mit gleichem Schema in einer Datei .objects/<...>.styles.yaml hinterlegt werden und via
objects:
styles: $include
ins package geladen. Existiert in einer Page sowohl ein globaler Style, als auch ein lokaler Style mit selben Namen, so wird der Style gemerged, d.h. für eine Page können so einzelne globale Styleeinstellungen überschrieben werden. Ein genestetes Binding von Größen ist nicht möglich.
Bis zur Version 7.3.0 wurden leicht andere Bezeichner für die Styleeigenschaften verwendet, die in nachfolgenden Versionen als (deprecated) zu betrachten sind.
some_style:
type: style
value:
fontSize: 2.5rem
color: "#ff8742"
backgroundColor: "#cf4fff"
height: 30px
width: 30px
Ist ein Style nur als lokaler Style definiert, so gilt der Zugriff auf properties weiter über die alten Keys durchzuführen. Sobald ein style allerdings als globaler Style definiert ist müssen die neuen Bezeichner verwendet werden - dies gilt ebenfalls, wenn ein lokaler Style ebenfalls als globaler style existiert.
Input/Output
Eine Page kann mit Inputs und Outputs versehen werden.
Diese erlauben den Zugriff auf primitive Page Variablen von außen, entweder schreibend oder lesend.
id: DEMO.demo_kundendetails
title: Kundendetails
type: mainPage
objectType: pagecontainer
inputs:
- detailKundenId
outputs:
- recordCount
Inputs können entweder über URL Query Parameter
<tenant>.businessexpress.cloud/page/DEMO.demo_kundendetails?detailKundenId=20
oder durch eine parent Page bereitgestellt werden.
- controlType: pageContainer
size: auto
id: DEMO.demo_kundendetails
data:
inputs:
detailKundenId:
$bind: kundenId
Outputs können nur von einer parent Page verwendet werden.
- controlType: pageContainer
size: auto
id: DEMO.demo_kundendetails
data:
outputs:
detailKundenId:
$bind: kundenId
Es ist zudem möglich zwei Variablen aus parent und child Page zu synchronisieren. Dadurch werden die Werte gleich gehalten, unabhängig davon in welcher Page dieser geschrieben wird.
- controlType: pageContainer
size: auto
id: DEMO.demo_kundendetails
data:
inputs:
detailKundenId:
$bind: kundenId
outputs:
detailKundenId:
$bind: kundenId
Validierung
Validierungen dienen dazu, Eingaben und Daten fachlich und formal zu prüfen, bevor sie weiterverarbeitet oder gespeichert werden.
Sie können sowohl an Page-Variablen als auch direkt an Entitätsfeldern definiert werden.
Hinweis:
Validierungen, die an Entitätsfeldern definiert sind, werden:
in die Page übernommen und dort frontendseitig ausgeführt
zusätzlich serverseitig im Backend vor
POST,PUTundPATCHOperationen ausgeführt
Damit stellen Entitätsvalidierungen eine zentrale, UI-unabhängige Validierungsschicht dar.
Validierungen an Variablen (Page)
Validierungen werden direkt an Variablen über die Property validation definiert. Eine Variable kann beliebig viele Validierungen besitzen.
data:
variables:
someVariable:
type: string
validation:
- <VALIDATOR1>
- <VALIDATOR2>
someInstance:
type: entityInstance
validation:
field1:
- <VALIDATOR1>
- <VALIDATOR2>
field2:
- <VALIDATOR3>
Jede Validierung ist ein Objekt mit mindestens folgenden Properties:
|
Feld |
Beschreibung |
|---|---|
|
|
Validierungstyp (siehe unten) |
|
|
Fehlertext bei invaliden Werten (nicht bei custom) |
Je nach Validierungstyp können zusätzliche Properties erforderlich oder optional sein.
Darüber hinaus haben die verschedenen Validatoren noch möglicherweise weitere Felder. Diese Felder und die aktuell zur Verfügung stehenden Validatoren sind
|
Typ |
Beschreibung |
Zusätzliche Parameter |
|---|---|---|
|
required |
Feld darf nicht leer sein |
- |
|
pattern |
Eingabe muss einem regulären Ausdruck entsprechen |
|
|
stringLength |
Mindest- und/oder Maximalanzahl an Zeichen |
|
|
allowedValues |
Eingabe muss einem der vorgegebenen Werte entsprechen |
|
|
range |
Wert muss zwischen zwei Grenzen liegen |
|
|
|
Format muss einer gültigen E-Mail entsprechen |
- |
|
custom |
Validierung erfolgt mit eigener Js Funktion |
|
Wird eine Variable mit Validator an ein Input Feld gebunden, so erhält der Benutzer bei Fehlschlagen der Validierung ein entsprechendes visuelles Feedback.
Abgrenzung: Page- vs. Entitätsvalidierungen
-
Variablenvalidierungen
-
gelten nur innerhalb der Page
-
werden ausschließlich frontendseitig ausgeführt
-
-
Entitätsvalidierungen
-
sind Teil der Entitätsdefinition
-
werden frontend- und backendseitig ausgeführt
-
sind unabhängig von konkreten Pages
-
verhindern bei invalidierung das schreiben in die Datenbank
-
Die Details zu Custom-Validierungen an Entitätsfeldern werden im folgenden Abschnitt beschrieben.
Custom-Validierungen
Neben den builtin-Validierungen unterstützt das Anwendungsframework auch Custom-Validierungen.
Diese werden verwendet, wenn Validierungslogik nicht deklarativ abbildbar ist oder zusätzlichen Kontext benötigt.
Für Custom-Validierungen gilt:
-
type: custommuss gesetzt sein -
das Property
messageentfällt vollständig -
stattdessen muss die Property
$scriptangegeben werden
Das $script enthält einen JavaScript-Funktionskörper, der bei der Validierung ausgeführt wird.
Rückgabewerte
Das Script muss einen der folgenden Werte zurückliefern:
-
true
→ der Wert ist valide -
string
→ der String wird als Validierungsfehlermeldung verwendet
Andere Rückgabewerte (z. B. false, null, undefined) sind nicht zulässig und führen zu undefiniertem Verhalten.
Zugriff im Script (Frontend-Ausführung)
Custom-Validierungen werden frontendseitig ausgeführt. Dabei stehen folgende Kontexte zur Verfügung:
-
$.event.value
→ aktueller Wert der Variable bzw. des Feldes, das validiert wird -
$
→ vollständiger Page-Kontext (Variablen, Controller, Events, …) -
insbesonder:
$.variables
→ Zugriff auf alle Page-Variablen
Beispiel: Custom-Validierung für eine Variable
validation:
type: custom
$script: | #js
if ( $.variables.var == 5) return 'value darf nicht 5 sein'
if ( $.event.value == 7 ) return 'value darf nicht 7 sein'
return true;
Bei der frontendseitigen Ausführung steht der komplette Pagekontext zur verfügung. Wird eine Custom Validierung an einem Entitätsfeld definiert besteht über $.dataset zumindest der Zugriff auf die zugehörige Entität. Außerdem besteht stets Zugriff auf den aktuellen Wert der Variable mit $.event.value.
Custom-Validierungen für Entitätsfelder
Custom-Validierungen können direkt an Entitätsfeldern in den entities.yaml-Dateien definiert werden.
Diese Validierungen sind nicht seitengebunden, sondern Teil der Entitätsdefinition.
Daraus ergeben sich zwei wichtige Eigenschaften:
-
Frontend
-
Die Validierungen werden beim Laden der Entität auf die Page übernommen
-
Die Ausführung erfolgt dort im bekannten Page-Kontext
-
-
Backend
-
Dieselben Validierungen werden auch bei
POST- undPUT-Requests ausgeführt -
Die Ausführung erfolgt im Backend
-
Es existiert dort kein Page-Kontext
-
Um dennoch fachliche Validierungen auf Basis der gesamten Entitätsinstanz zu ermöglichen, wurde der Kontext
-
$.dataset
eingeführt und repräsentiert immer die vollständige Entitätsinstanz, die gerade validiert wird.
Beispiel für Custom Entitätsfeldvalidierung
validation:
type: custom
$script: | #js
if ( $.dataset.var == 5) return 'value von var der aktuellen Entität darf nicht 5 sein'
if ( $.event.value == 7 ) return 'value darf nicht 7 sein'
if ( $.dataset.var + $.datset.another_field > 17) return 'Zugriff auf andere Felder mgl'
return true;
Erläuterung:
-
$.event.valuebezieht sich ausschließlich auf das aktuell validierte Feld -
$.datasetermöglicht feldübergreifende Validierungen innerhalb derselben Entität -
Die Validierung ist:
-
frontendseitig lauffähig
-
backendseitig lauffähig
-
unabhängig vom UI-Kontext
-
Postgresql-Enum Definitionen
Ein Enum (Aufzählungstyp) ist ein vordefinierter Satz erlaubter Werte für ein Entitätsfeld. Im Anwendungsframework werden Enums als native PostgreSQL-Typen (CREATE TYPE data.<name> AS ENUM (…)) angelegt und gleichzeitig als OData-Enum-Typen im Metadaten-Schema exponiert. Ein Enum-Feld in einem entityContainer wird automatisch als Dropdown mit den definierten Werten angezeigt.
Enum-Definition
Enums werden im package unter objects->enums definiert und haben je Eintrag nur die beiden Felder
|
Feld |
Beschreibung |
|---|---|
|
|
Bezeichner des Datentypes. Muss mit |
|
|
Enumwerte als Liste. Die Einträge dieser Liste sind entweder einfache Strings, oder Objecte mit |
Beispiel
enums:
- name: mypkg_status
values:
- Offen
- In Bearbeitung
- Abgeschlossen
- value: low
displayValue: Niedrig
- value: medium
displayValue: Mittel
- value: high
displayValue: "${mypkg.STATUS_HIGH}"
Verwendung des displayValues
Neben der Definition as einfacher String kann ein Enumwert auch als Kombination von value und displayValue definiert werden. Aktuell (Stand: 11.0.0) wird dieser displayValueallerdings nur für die Verwendung des displayValuesim zugehörigem Inputfeld in einem Entitycontainer verwendet. Als Wert kann hier entweder ein konstanter String verwenet werden, oder ein Übersetzungsschlüssel in der Form ${<Package>.<Key>. zu beachten ist hierbei, dass hier die Angabe des Packagekeys Pflicht ist.
Verwendung von Enums in Entitätsdefinitionen
Ein Enum-Feld wird in der Entitätsdefinition gesetzt, indem dbType auf den Enum-Namen gesetzt wird:
fields:
- name: priority
dbType: mypkg_priority
label: Priorität
Definiert dieses Feld dann keine AllowedValues-Validierung , so wird ein generierter bei Verwendung als entityInstance im Frontend bereitgestellt.
Fallstricke und sonstige Informationen
Aufgrund der technischen Gegebenheiten von PostgresqlEnums gibt es aktuell nur eine eingeschränkte Bearbeitbarkeit der Enums:
-
Das entfernen von Enum Values ist nicht möglich
-
Neue Werte sollten stets am Ende eingefügt werden
-
Ein Umbenennen eines Enums wird nicht unterstützt. Wird der Name in der YAML-Definition geändert, behandelt das System dies als vollständig neuen Enum-Typ und legt data.<neuer_name> als neuen PostgreSQL-Typ an – der alte Typ bleibt dabei unverändert in der Datenbank bestehen. Eine automatische Migration ist nicht möglich, da PostgreSQL keinen impliziten Cast zwischen zwei verschiedenen Enum-Typen kennt.
Der Name eines postgres enums wird case-insensitive interpretiert.