Javascript im Frontend
be Dynamic YAML Templates
Ein Designprinzip des be Portals ist eine umfassende, individuell konfigurierbare Anpassbarkeit. Damit kann das be Portal an die Anforderungen und Bedürfnisse des Benutzers angepasst werden, ohne den Code im Produkt zu ändern. Diese Anpassbarkeit spiegelt sich auch in der Konfiguration, den Pages und Workflows wider.
Dynamische YAML-Konfiguration im Frontend erfolgt über YAML und JavaScript und kann für viele Felder genutzt werden. Zu beachten ist, dass das Ergebnis des JavaScript dem Werteschema des Feldes entspricht.
Nutzung im YAML Format
Die dynamischen Elemente im Schema werden über script_or_<type>
Definitionen im YAML Schema beschrieben.
$expr
Ein JavaScript Ausdruck (expression
), welches den Wert der Eigenschaft dynamisch zur Laufzeit berechnet.
Der JavaScript Code kann über die Variable $
auf Kontextdaten zugreifen.
Beispiele:
`Berechneter` + ` Text`
`Wert: ` + $.variables.custom_var
$statement
Ein JavaScript-Code, der den Wert der Eigenschaft dynamisch zur Laufzeit berechnet.
Der JavaScript-Code muss den Wert per return
zurückgeben.
Der JavaScript-Code kann über die Variable $
auf Kontextdaten zugreifen.
Beispiele:
return `Berechneter` + ` Text`
return `Wert: ` + $.variables.custom_proc_var
$script
Ein JavaScript-Code, der in der Regel durch eine Aktion ausgelöst wird (bspw. Button → Klick-Event, EntityGrid → onLoaded-Event).
Der JavaScript-Code kann beliebige Aktionen ausführen, wie z.B. Variablenzuweisungen oder Backend-Aufrufe.
Der JavaScript-Code kann über die Variable $
auf Kontextdaten zugreifen.
Beispiele:
$.variables.var1 = 'Hello World';
backend.execute($.variables.backendAction);
Variablenzuweisungen werden innerhalb eines $script
synchron durchgeführt. Erst nach dem letzten Ausdruck innerhalb dieses $script
erfolgt jedoch das “Speichern” der Variablenänderungen (wodurch z.B. abhängige Controls aktualisiert werden).
Wenn Variablenänderungen schon während der $script
-Ausführung gespeichert werden sollen, ist der Aufruf von await $.controller.flush();
erforderlich.
Außerdem werden innerhalb eines $script
Variablen vom Typ entityInstance
nicht automatisch aktualisiert, wenn sich bspw. deren primaryKey
ändert. Dies passiert erst nach vollständig $script
-Ausführung oder nach einem await $.controller.flush()
-Aufruf. Wenn die EntityInstance jedoch schon innerhalb des $script
aktualisiert werden soll, kann dies mit dem Aufruf von await $.controller.refreshEntityInstance('<entityInstanceName>')
erreicht werden.
Kontext Objekte
Der JavaScript-Code bekommt beim Aufruf einen Kontext übergeben. Dieser Kontext stellt den aktuellen Zustand der be Portal Oberfläche für das Skript dar, während es ausgeführt wird. Der Kontext hat klar definierte Eigenschaften und enthält auch einige Hilfsfunktionen, die bei der Ausführung des Skripts verwendet werden können.
Innerhalb des Kontexts werden verschiedene Klassen von Objekten zur Verfügung gestellt. Allgemein gibt es das GenericContextObject
, sowie spezielle Klassen auf Basis von YAML Objekten, die mit Hilfsfunktionen zum Auslesen der YAML Informationen angereichert werden.
Der JavaScript Code kann über die Variable $
auf Kontextdaten zugreifen. Verfügbare Kontextdaten sind:
$.pageId
$.loginUser
(Information des eingeloggten Users)$.users
(User-bezogene Funktionen)$.format
(Formatierungsfunktionen)$.variables
(im Fall einer Page mit definierten Variablen)$.controller
(im Fall einer JavaScript-Ausführung per$script
)$.event
(im Fall eines ausgelösten Events)$.processVariables
(im Fall eines Workflow Formulars)$.tableRowContext
[deprecated] (hier stehen die Werte der aktuellen Tabellenzeile zur Verfügung)$.dataSet
(hier stehen die Werte der aktuellen Tabellenzeile zur Verfügung)$.ocrData
(im Fall eines durch OCR analysierten PDF-Dokuments im Eingangsrechnungsworkflows)$.workflow
(Workflow-spezifische Funktionen)$.dialog
(Funktionen für das Management von Sub-page Modals)$.customControl
(Zugriff auf die iFrames vonCustomControls
für die Kommunikation mit diesen)$.debug
(Hilfs-Funktionen zum debuggen)$.notify
(Funktionen zum Anzeigen von Toasts)$.command
(Funktionen zum Ausführen von Commands)$.backend
(Funktionen zum Ausführen von beas Backend Skripten)$.isMobile
(Hilfs-Funktion um herauszufinden ob man sich auf einem mobilen Device befindet)$.expertModeEnabled()
(Funktion um herauszufinden, ob der Expertenmodus aktiviert ist)$.navigation
$.documents
pageId
ID der Page durch welche das JavaScript ausgeführt wird im Format:
<Package-Key>.<PageId>:<Unique-Identfifier>
Der Identifier wird zur Laufzeit erstellt, damit mehrere Page Instanzen mit der gleichen ID unterschieden werden können.
Beispiel:
id: BSP.beispiel-page
controls:
- controlType: button
label: Zeige Page ID
events:
click:
$script: |
debug.log($.pageId);
loginUser
Informationen zum eingeloggten User
Eigenschaft | Beschreibung |
---|---|
| Anzeigename des Benutzers |
| E-Mail Adresse aus dem Personalstamm |
| Array von Gruppen IDs zu welchen der Beutzer zugeordnet ist |
| Array von Rollennamen zu welchen der Beutzer zugeordnet ist |
|
|
| Datensatz ID im Personalstamm |
| Eindeutiger Benutzerschlüssel.
ID des jeweiligen Datensatzes |
Methode | Beschreibung |
---|---|
| Gibt an ob der Benutzer zu einer Rolle gehört. Der Vergleich erfolgt |
| Gibt an ob der User |
| Gibt an ob der User |
| Gibt ein Array von Package Rollen zurück, zu denen Der User gehört. Der Vergleich erfolgt |
Beispiel:
controls:
- controlType: button
label: Zeige Login User
events:
click:
$script: |
$.debug.log($.loginUser);
$.debug.log($.loginUser.isPackageAdmin('ERU'));
$.loginUser.packageRoles('ERU').forEach(role => $.debug.log(role));
users
Über $.users
stehen Hilfsfunktionen für den Umgang mit User-Daten bereit. Nachfolgende Funktionen sind darin enthalten.
Methoden | Beschreibung |
---|---|
| Gibt den dem |
Beispiel:
controls:
- controlType: button
label: Zeige Login User
events:
click:
$script: |
debug.log($.users.keyToName('U65'));
debug.log($.users.keyToName($.loginUser.userKey));
format
Über $.format
stehen Formatierungsfunktionen bereit.
Methode | Beschreibung |
---|---|
| Der Optional können
JS
Weitere Optionsmöglichkeiten werden im Unterpunkt “mögliche Optionen” beschrieben. |
| Der Optional können
JS
Weitere Optionsmöglichkeiten werden im Unterpunkt “mögliche Optionen” beschrieben. |
| Der Optional können
JS
Weitere Optionsmöglichkeiten werden im Unterpunkt “mögliche Optionen” beschrieben. |
| Der Wurde der Parameter |
Beispiel:
controls:
- controlType: button
label: Zeige Login User
events:
click:
$script: |
const now = new Date(); // 24.05.2024 - 13:05:23 Uhr
debug.log($.format.date(now)); // Ausgabe: "24.05.24"
debug.log($.format.datetime(now)); // Ausgabe: "24.05.24, 13:05:23"
debug.log($.format.time(now)); // Ausgabe: "13:05:23"
// mit Optionen:
debug.log($.format.datetime(now, {weekday:'long',
year:'numeric',
month:'long',
hour12:true}));
// Ausgabe: "Freitag, 24. Mai 2024 um 1:05:23 PM"
mögliche Optionen:
Bei den $.format
- Methoden date
, datetime
und time
ist es möglich options
optional bei der Erstellung mitzugeben. Diese options
müssen als Objekt definiert werden und können folgende Parameter mit folgenden Werten enthalten:
year
- Repräsentation des Jahres - mögliche Werte: 'numeric'
und '2-digit'
month
- Repräsentation des Monats- mögliche Werte: 'numeric'
, '2-digit'
, 'long'
, 'short'
, 'narrow'
day
- Repräsentation des Tages- mögliche Werte: 'numeric'
und '2-digit'
hour
- Repräsentation der Stunde - mögliche Werte: 'numeric'
und '2-digit'
minute
- Repräsentation der Minute - mögliche Werte: 'numeric'
und '2-digit'
second
- Repräsentation der Sekunde - mögliche Werte: 'numeric'
und '2-digit'
Weitere Optionen sind in der offiziellen Mozilla-Dokumentation zu finden: Parameter DateTimeFormat
variables
Die Variablen einer Page können über den Javascript-Kontext gelesen und geschrieben werden. Im Beispiel wird eine Variable matchcode
mit dem Wert TOPF_B1
vorbelegt.
Im Input kann der Matchcode angepasst werden und per Button-Klick wird der Name in der Debug-Konsole ausgegeben. Mit dem Löschen-Button wird der Matchcode auf einen leeren String gesetzt.
# article.page.yml
data:
variables:
matchcode:
type: string
value: TOPF_B1
controls:
- controlType: input
type: text
value:
$bind: matchcode
- controlType: button
label: Zeige Matchcode
events:
click:
$script: |
debug.log($.variables.matchcode);
- controlType: button
label: Lösche Matchcode
color: danger
events:
click:
$script: |
$.variables.matchcode = '';
controller
Der $.controller
-Kontext steht in $script
-Codes bereit und unterstützt bei der Steuerbarkeit von Asynchronität.
Methode | Beschreibung |
---|---|
|
|
|
|
| Gibt zurück, ob die Ausführung des synchronen |
Beispiel:
Anzeige des Feldes bez1
zur einer artnr
mit Lade-Text (während die Daten geladen werden) und Benachrichtigung (sobald die Daten geladen wurden)
data:
variables:
artnr:
type: string
value: TOPF_B1
article:
type: entityInstance
source: odata
entity: Dab010
primaryKey:
$bind: artnr
loadingText:
type: string
controls:
- controlType: text
value:
$bind: loadingText
- controlType: input
type: text
value:
$bind: artnr
- controlType: text
value:
$bind: article.bez1
- controlType: button
label: Artikel TOPF_B2
events:
click:
$script: |
$.variables.loadingText = 'Lade Daten...';
await $.controller.flush(); // notwendig, damit die Variablenänderung gespeichert und der Lade-Text im Control angezeigt wird
$.variables.artnr = 'TOPF_B2';
// $.variables.article.bez1 hätte hier noch den Wert der vorherigen artnr (TOPF_B1)
await $.controller.refreshEntityInstance('article');
// $.variables.article.bez1 hat hier den neuen Wert
notify.success('Artikel TOPF_B2 hat die Bezeichnung ' + $.variables.article.bez1);
$.variables.loadingText = '';
// $.controller.flush() ist hier nicht notwendig, da es am Ende des $script automatisch ausgeführt wird
event
Eigenschaften | Beschreibung |
---|---|
| Eindeutige, intern vergebene ID des Oberflächen Controls |
| Eindeutige Page ID |
Je nach Event hat das Objekt weitere Eigenschaften.
beforeValueChanged
/ afterValueChanged
Eigenschaften | Beschreibung |
---|---|
| Wert der Variablen vor der Änderung |
| Wert der Variablen nach der Änderung |
| Name der Variable die sich geändert hat. |
processVariables
processVariables
sind das gleiche wie variables
mit dem Unterschied, dass diese Variablen vom Prozess definiert werden und nicht von der Page.
tableRowContext
[DEPRECATED]: Der tableRowContext
ist veraltet, sodass eine einwandfreie Funktionsweise nicht mehr garantiert ist. Stattdessen sollte dataSet
(Javascript im Frontend | dataSet) verwendet werden.
Der tableRowContext
ist genauso aufgebaut wie die Prozessvariablen. Es ist jedoch ein Objekt mit allen Spalten als Eigenschaften und dem Zelleninhalt als Wert. Folgende Tabelle:
| Name | City | Amount |
------------------------
| Max | Ulm | 1337 |
sieht im Kontext so aus:
$ = {
tableRowContext: {
Name: {
type: "Text",
value: "Max"
},
City: {
type: "Text",
value: "Ulm"
},
Amount: {
type: "Amount",
value: 1337
}
}
}
dataSet
Bei Listen-Controls existiert bei bestimmten Eigenschaften ein dataSet
-Objekt, um datensatzspezifische Skripte schreiben zu können. Dieses Objekt enthält die Felder des jeweiligen Datensatzes.
Folgende Tabelle:
| Name | City | Amount |
------------------------
| Max | Ulm | 1337 |
| Tim | Berlin | 4711 |
sieht im zeilenspezifischen Kontext (z.B. beim Highlighting) so aus:
// Zeile 1:
$ = {
dataSet: {
Name: "Max",
City: "Ulm",
Amount: 1337
}
}
// Zeile 2:
$ = {
dataSet: {
Name: "Tim",
City: "Berlin",
Amount: 4711
}
}
ocrData
Das ocrData
Objekt steht im Kontext zur Verfügung, wenn es die Prozessvariable std_proc_be_ocr_result
gibt.
interface OcrContextObject {
[propertyName: string]: any;
isAvailable(): boolean;
formatConfidence(propertyName: string): string;
}
Der ocrData
Kontext enthält alle Properties die hier (https://businessexpress.cloud/docs/be-documents-service/latest/index.html) definiert sind, sofern sie von der OCR Erkennung erkannt wurden.
Es gibt außerdem die Methode isAvailable()
, mit der geprüft werden kann, ob das OcrContextObject
Eigenschaften enthält und die Methode formatConfidence()
, mit der die Confidence der übergebenen Property als formatierten String zurückgegeben wird, z. B. 0.87
-> 87 %
Beispiel:
$.ocrData = {
total: {
value: 1378.37,
rawValue: "1378,37 €",
confidence: 0.86,
},
}
$.ocrData.isAvailable(); // = true
$.ocrData.formatConfidence('total'); // = '86.0 %'
workflow
$.workflow
steht auf Pages zur Verfügung, die Teil eines Workflows sind.
ocrData: OcrContextObject;
complete: () => Promise<void>;
completeWithVariables: (variables: Record<string, any>) => Promise<void>;
error: (errorCode: string) => Promise<void>;
escalate: (escalationCode: string) => Promise<void>;
saveVariable: (variableName: string) => Promise<void>;
setNextUser: (userKey: string) => Promise<void>;
setNextGroups: (groupKeys: string[]) => Promise<void>;
userAssignment: (definition: Partial<UserAssignmentDefinition>, callback: () => void) => void;
confirmation: (definition: Partial<ConfirmationDefinition>, callback: () => void) => void;
isAssignedToMe: () => boolean;
assignedUser: () => string;
Methoden | Beschreibung |
---|---|
| Schließt den aktuellen Workflow-Schritt ab |
| Schließt den aktuellen Workflow-Schritt ab. Es kann ein |
| Löst für den aktuellen Workflow-Schritt den Fehler mit dem übergebenen Fehlercode aus. |
| Löst für den aktuellen Workflow-Schritt die Eskalation mit dem übergebenen Eskalations-Code aus. |
| Speichert die angegebene Page-Variable sofort in Camunda ab. Sofern die Variable in Camunda nicht existiert, wird sie erstellt. |
| Kann in |
| Kann in |
| Kann in
|
| Zeigt einen Confirm-Dialog mit der übergebenen Definition an.
|
| Gibt zurück, ob der ausgewählte Task dem aktuell angemeldeten User zugewiesen ist. |
| Gibt für den ausgewählten Task den |
Eigenschaften | Beschreibung |
| Siehe Beschreibung |
dialog
Erlaubt die Nutzung von Sub-Page Modals.
Beispiel:
controls:
- controlType: button
label: btn
events:
click:
$script: |
$.dialog.show(
'PKG.page'
(event) => {debug.log(JSON.stringify(event));},
{size: 'medium', 'title' : 'hello world'});
Dies erzeugt ein Modal, dass die Page PKG.page
. Der callback der hier mitgegeben wird ist relevant für weitere dialog
Funktionen die in der entsprechenden subpage benutzt werden können (siehe unten). Zusätzlich hat das Modal eine Toolbar mit Button, die in der aufgerufenen Page definiert werden können. Die Definition von diesen findet innerhalb von contributes
statt.
Zum Beispiel:
contributes:
dialog:
buttons:
- label:
$expr: |
$.variables.someLabel + "!";
color: danger
disabled:
$bind: isDisabled
events:
click:
$script: |
$.dialog.cancel(),
- label: speichern
color: success
events:
click:
$script: |
$.dialog.success({ out: "resultData"})
Dies erzeugt zwei Button in der Toolbar des Modals. Zusätzlich stehen in der Subpage die Funktionen:
$.dialog.cancel(payload)
, $.dialog.close(payload)
und $.dialog.success(payload)
zur Verfügung, wobei der payload
optional ist. Alle diese Funktionen schließen das Modal und führen den callback der $.dialog.show
Funktion aus, wobei
event = {
resultCode: /* 'close', 'success' or 'cancel' */,
resultData: payload
}
ist.
customControls
Beispiel:
controls:
- controlType: custom
name: myCustomControl
id: idMyCustomControl
width: 20vh
events:
receiveMessage:
$script: |
debug.log('receive iFrame: ' + $.message);
- controlType: button
label: SendStaticMessage
events:
click:
$script: |
$.customControl('idMyCustomControl').postMessage("Statische Nachricht");
debug
Hilfs Funktionen zum Debuggen
Methoden | Beschreibung |
---|---|
| Gibt Nachricht auf der Browser Konsole aus |
| Gibt Nachricht auf der Browser Konsole aus aber nur wenn der Expertenmodus aktiv ist |
Beispiel:
controls:
- controlType: button
label: Debug Log
events:
click:
$script: |
$.debug.log('Button Clicked!')
notify
Hilfs Funktionen zum Anzeigen von Toasts
Methoden | Beschreibung |
---|---|
| Zeigt grünen Toast an |
| Zeigt roten Toast an |
| Zeigt blauen Toast an |
| Zeigt orangen Toast an |
| Zeigt je nach Typ einen Toast mit entsprechender Farbe an
|
Beispiel:
controls:
- controlType: button
label: Toasts zeigen
events:
click:
$script: |
$.notify.success('Erfolgreich');
$.notify.error('Fehler');
$.notify.info('Erledgit');
$.notify.warning('Wenig Speicher');
$.notify.show('success', 'Erfolgreich');
command
Funktionen zum Ausführen von Commands
Methoden | Beschreibung |
---|---|
| Führt das |
Beispiel:
pageId: BSP.command-page
commands:
- name: ExampleCommand
label: Beispiel Kommande
action:
$script: |
$.debug.log('Beispiel Kommando ausgeführt!')
controls:
- controlType: button
label: Kommando ausführen
events:
click:
$script: |
$.command.execute('BSP.command-page.ExampleCommand')
backend
Funktionen zum Ausführen von beas Backend Skripten
Methoden | Beschreibung |
---|---|
| Führt im beas die Funktion mit dem angegebenen Namen aus. |
Beispiel:
controls:
- controlType: button
label: Einbuchen
events:
click:
$script: |
$.backend.execute('bdeEinbuchen')
isMobile
Hilfs-Funktion um herauszufinden ob man sich auf einem mobilen Device befindet
Beispiel:
controls:
- controlType: button
label: Mobilgerät?
events:
click:
$script: |
$.debug.log(`Mobil (true/false)? ${$.isMobile}`)
expertModeEnabled
Hilfs-Funktion um herauszufinden, ob der Expertenmodus aktiv ist.
Wenn der Expertenmodus geändert wird, erfolgt sofort eine Aktualisierung des JavaScript-Kontexts.
Beispiel:
controls:
- controlType: text
value: Experteninformation nur im Expertenmodus sichtbar
visible:
$expr: | # js
$.expertModeEnabled()
navigation
Funktion zur Navigation zu einer URL.
controls:
- controlType: button
events:
click:
$script: | # js
$.navigation.navigate('https://www.google.de/', '_self');
// $.navigation.navigate('/administration/system-settings');
confirm
Hilfsfunktion zur Erstellung von Confirm-Dialogen.
Methoden | Beschreibung |
---|---|
| Erstellung eines Custom-Dialogs mit folgenden Parametern:
|
| Erstellung eines Default-Dialogs mit “Abbrechen” und “Bestätigen” Button mit folgenden notwendigen Parametern:
optionale Parameter:
|
| Erstellung eines Custom Dialogs mit Eingabefeld. Die Callbacks, die in den Button definiert werden haben hierbei als Argument den Eingabewert. |
- controlType: button
label: Neuen Artikel anlegen
events:
click:
$script: |
const artikelAnlegen = function(type) {
$.variables.newArticleType = type;
$.backend('createArticle');
}
$.confirm.show(
'Artikel anlegen',
'Welchen Artikel möchten Sie anlegen?',
[
{ label: 'Kaufteil', callback: () => artikelAnlegen('T'), type: 'default', stylingMode: 'contained' },
{ label: 'Baugrupppe', callback: () => artikelAnlegen('B'), type: 'danger', stylingMode: 'outlined' },
{ label: 'Artbeitswert', callback: () => artikelAnlegen('A'), type: 'success', stylingMode: 'text' },
],
'medium'
)
- controlType: button
label: Artikel löschen
events:
click:
$script: |
const articleNumber = $.variables.articleNumber;
const deleteArticle = function() {
$.variables.articles.$.delete();
$.notify.success(`Der Artikel wurde ${articleNumber} gelöscht`);
$.backend('reorgArticles');
}
$.confirm.default(
'Artikel löschen',
`Möchten Sie den Artikel ${articleNumber} wirklich löschen?`,
deleteArticle
)
documents
Methoden | Beschreibung |
---|---|
| Lädt das Dokument mit der angegebenen |
Beispiel:
- controlType: button
label: Download
events:
click:
$script: |
$.documents.download($.variables.documentUuid);
messaging
Grundlagen des Messagings: https://dontenwill.atlassian.net/wiki/spaces/BPOH/pages/986841157
Methoden | Beschreibung |
---|---|
| Erstellt einen |
MessagingContext:
Methoden | Beschreibung |
---|---|
| Versendet eine MQTT-Nachricht in dem als |
Beispiel:
- controlType: button
label: Jump via MQTT for my User and User 'U2'
events:
click:
$script: |
$.messaging.user().publish('jump', {'key': 'article', 'id': 123});
$.messaging.user('U2').publish('jump', {'key': 'article', 'id': 123});
odata
Methoden | Beschreibung |
---|---|
| Führt die ungebundene OData Action aus und gibt das Ergebnis zurück. Der |
| Führt die ungebundene OData Funktion aus und gibt das Ergebnis zurück. Die Parameter können als Objekt übergeben werden, wobei der Name des Parameter der Property-Name ist. |
| Führt die OData Action aus und gibt das Ergebnis zurück. Der |
| Führt die OData Action aus und gibt das Ergebnis zurück. Der |
| Führt die OData Funktion aus und gibt das Ergebnis zurück. Die Parameter können als Objekt übergeben werden, wobei der Name des Parameter der Property-Name ist. |
| Führt die OData Funktion aus und gibt das Ergebnis zurück. Die Parameter können als Objekt übergeben werden, wobei der Name des Parameter der Property-Name ist. |
Beispiel:
- controlType: button
label: OData Aktion
events:
click:
$script: |
await $.odata.executeAction('NeuberechngungPreise', {articleType: 'A'});
- controlType: button
label: OData Funktion
events:
click:
$script: |
await $.odata.executeFunction('HoechsterPreis', {articleNumber: 'JFK_4747_AKJF'});
executeEntityAction: async (entityName: string, primaryKeyValue: any, actionFQN: string, body: Record<string, any> = null): Promise<any> => {
const service = StaticInjector.get<ODataMethodsService>(ODataMethodsService);
return service.executeEntityAction(entityName, primaryKeyValue, actionFQN, body);
},
executeEntityCollectionAction: async (entityName: string, actionFQN: string, body: Record<string, any> = null): Promise<any> => {
const service = StaticInjector.get<ODataMethodsService>(ODataMethodsService);
return service.executeEntityCollectionAction(entityName, actionFQN, body);
},
executeFunction: async (functionName: string, params: Record<string, any> = null, namespace: string = 'OData.Beng'): Promise<any> => {
const service = StaticInjector.get<ODataMethodsService>(ODataMethodsService);
return service.executeUnboundFunction(functionName, params, namespace);
},
executeEntityFunction: async (entityName: string, primaryKeyValue: any, functionFQN: string, params: Record<string, any> = null): Promise<any> => {
const service = StaticInjector.get<ODataMethodsService>(ODataMethodsService);
return service.executeEntityFunction(entityName, primaryKeyValue, functionFQN, params);
},
executeEntityCollectionFunction: async (entityName: string, functionFQN: string, params: Record<string, any> = null): Promise<any> => {
const service = StaticInjector.get<ODataMethodsService>(ODataMethodsService);
return service.executeEntityCollectionFunction(entityName, functionFQN, params);
},
Modularisierung von JavaScript Code
Oft möchte man gleichen Code in mehr als einer Expression verwenden. Dieser Code kann in Module ausgelagert werden, welche automatisch für alle Javascript Elemente einer page
zur Verfügung stehen.
Im folgenden wird beschrieben, wie man Module in einer Page bereitstellt und wie diese Module zu definieren sind.
Modul definieren und verwenden
Ein Modul kann Funktionen, Konstanten und Klassen exportieren. Es wird nicht automatisch alles exportiert, was in dem Modul definiert ist, es muss explizit angegeben werden, welche Teile exportiert werden sollen.
Export von Funktionen:
// Datei: mathUtils.js
const PI = 3.1415;
function square(num) {
return num * num;
}
function circularArea(radius) {
return PI * square(radius);
}
// Es wird nur die Funktion circularArea exportiert.
// square und PI sind in den Expressions also nicht verfügbar.
return { circularArea }
Export von Konstanten und Klassen
// Datei: articleHelper.js
const ArticleNoLength = 20;
class ArticleHelper {
trimArticleNumber(articleNumber) {
return articleNumber.substring(0, ArticleNoLength);
}
}
return { ArticleNoLength, ArticleHelper }
Module brauchen einen Namen, damit diese verwendet werden können. Der Name wird entweder in der Page-Definition angegeben oder leitet sich vom Namen der JS-Datei ab.
- controlType: inputContainer
controls:
- controlType: label
value: "Artikel-Nummer"
- controlType: input
type: text
value:
$statement: |
const helper = new articleHelper.ArticleHelper();
return helper.trimArticleNumber("MUTTER M-1");
Inline Module
JS Module können direkt in einer Page definiert werden. Alle exportierten Funktionen stehen in den Expressions und Statements auf der Page zur Verfügung
import:
- name: base64
src: |
function decode(encoded) {
return atob(encoded);
}
function encode(decoded) {
return btoa(decoded)
}
// Export der Funktionen
return { decode, encode }
Module in JS Dateien
Wenn Module größer werden oder wenn Sie auf verschiedenen Pages verwendet werden sollen, macht es Sinn, diese in eigene Dateien auszulagern. Der Name der JS Datei ist dabei der Name des Moduls.
Module müssen nicht explizit in Pages importiert werden. Die Verfügbarkeit der Module leitet sich von der Ordner-Struktur des .pages
Ordners ab. Ein Modul ist in allen Pages verfügbar, welches sich im gleichen Ordner befindet. Außerdem ist es in allen Pages in Unterordnern verfügbar.
Im folgenden Beispiel ist das Modul utils
auf allen Pages verfügbar. Das Module articleHelper
jedoch nur auf der Page article
Projekt Root-Ordner
|
|_ .pages
|____ article
|______ article.page.yml
|______ articleHelper.js
|____ main.page.yml
|____ utils.js
Debugging von Skripten
Skripte, die auf Pages definiert werden oder die aus JavaScript Modulen kommen, können im Browser debugged werden. Es können Breakpoints gesetzt werden, an denen die Ausführen des Programms angehalten wird. Dabei kann der komplette Kontext untersucht werden.
Die Ausführung wird nur angehalten, wenn die DevTools des Browsers geöffnet sind.
Beispiel zum Setzen eins Breakpoints:
controls:
- controlType: button
label: Debugging von Skripten
events:
click:
$script: |
const now = new Date();
const text = `heutiges Datum: ${now}`;
debugger; // diese Zeile setzt einen Breakpoint
$.notify.info(text);
Fehlerhandling von Skripten
Skripte, die auf Pages definiert werden oder die aus JavaScript Modulen kommen, können Kompilierfehler enthalten und somit unbrauchbar werden. Damit Page-Entwickler über derartige Fehler informiert werden, erfolgt eine Evaluierung dieser JavaScripts zu dem String Fehler in der JavaScript-Property!
. Darüber hinaus wird der Fehler mit Zusatzinformationen auf der Browser-Konsole ausgegeben, um die Fehlersuche zu vereinfachen.
Beispiel eines fehlerhaften JavaScripts:
controls:
- controlType: text
value:
$expr: |
'thisIsInvalidJavaScript'{{{}}}
Beispiel-Fehlerausgabe auf der Konsole:
VM2746:56 Custom JavaScript is invalid.
Path: <pageId>.text.value
Error:
SyntaxError: Unexpected token '{'
at [...]
Code:
'thisIsInvalidJavaScript'{{{}}}