Beispiel-Sammlung
Hier findest du die Beispiele aller Module.
Badge
Badge: Basis

Beschreibung
Wir möchten mithilfe von einem Badge den aktuell gewählten Status in einem dynamischen Ninox-Auswahlfeld anzeigen. Dabei sollen auch die Hintergrundfarbe und das Symbol des gesetzten Status korrekt dargestellt werden.
Die Status-Optionen als Grundlage für die dynamische Auswahl befinden sich in einer Ninox-Tabelle namens "Status". Hierin werden die Bezeichnung, Farbe und das Symbol der Option gesetzt.
Code des Beispiels
let statusRecord := record(Status,number('Status-Auswahl'));
html(raw(GIP_master({})) +
raw(GIP_badge({
uniqueId: "StatusAnzeige" + Nr,
embedded: false,
style: "color: black; border: none; background-color: " + statusRecord.Farbe + ";",
blocks: [{
value: GIP_materialSymbols(parseJSON(statusRecord.Symbol))
}, {
value: statusRecord.Bezeichnung
}]
})))let statusRecord := record(Status,number('Status-Auswahl'));
GIP_badge({
uniqueId: "StatusAnzeige" + Nr,
embedded: true,
style: "color: black; border: none; background-color: " + statusRecord.Farbe + ";",
blocks: [{
value: GIP_materialSymbols(parseJSON(statusRecord.Symbol))
}, {
value: statusRecord.Bezeichnung
}]
})Badge: Checkbox mit Material Symbol
Beschreibung
Wir möchten eine einfache Checkbox erstellen. Dafür nutzen wir die Material-Symbols "check_box" (angehakte Checkbox) und "check_box_outline_blank" (leere Checkbox). Um die Checkbox und den Text "Aufgabe erledigt?" zu gruppieren, nutzen wir in diesem Fall ein GIP-Badge. Zusätzlich dient das Badge auch dazu, die Update-Action für das Ninox-'Ja / Nein'-Feld zu bauen. Mit entsprechendem Styling, kann dasselbe Ergebnis aber auch mit Layout, Interaction und Card erzielt werden.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_badge({
uniqueId: "Checkbox" + Nr,
embedded: false,
direction: "horizontal",
class: "",
style: "background-color: inherit; color: inherit; border: none;",
blocks: [{
class: "",
style: "",
value: if 'Ja / Nein' = true then
GIP_materialSymbols({
embedded: true,
style: "",
scalingFactor: 0,
weight: 0,
filling: 1,
color: "",
secondColor: "#bcf0ad",
icon: "check_box"
})
else
GIP_materialSymbols({
embedded: true,
style: "",
scalingFactor: 0,
weight: 0,
filling: 0,
color: "",
secondColor: "",
icon: "check_box_outline_blank"
})
end
}, {
class: "",
style: "",
value: "Aufgabe erledigt?"
}],
actions: [{
trigger: "click",
scripts: [{
type: "update",
recordId: raw(Nr),
fieldId: fieldId(this, "Ja / Nein"),
value: not 'Ja / Nein'
}]
}]
})))GIP_badge({
uniqueId: "Checkbox" + Nr,
embedded: true,
direction: "horizontal",
class: "",
style: "background-color: inherit; color: inherit; border: none;",
blocks: [{
class: "",
style: "",
value: if 'Ja / Nein' = true then
GIP_materialSymbols({
embedded: true,
style: "",
scalingFactor: 0,
weight: 0,
filling: 1,
color: "",
secondColor: "#bcf0ad",
icon: "check_box"
})
else
GIP_materialSymbols({
embedded: true,
style: "",
scalingFactor: 0,
weight: 0,
filling: 0,
color: "",
secondColor: "",
icon: "check_box_outline_blank"
})
end
}, {
class: "",
style: "",
value: "Aufgabe erledigt?"
}],
actions: [{
trigger: "click",
scripts: [{
type: "update",
recordId: raw(Nr),
fieldId: fieldId(this, "Ja / Nein"),
value: not 'Ja / Nein'
}]
}]
})Badge: Globale CSS-Classes

Beschreibung
Wir möchten ein GIP-Badge stylen und dafür eine globale CSS-Class nutzen. Dafür können wir entweder eine Auswahl an GIP-Color-Classes nutzen (teilweise basierend auf Ninox-eigenen Button-Stylings) oder wir legen eine eigene CSS-Class an. Wie im Bild zu sehen, wird durch die Class auch das Material-Symbol im Text beeinflusst. Das liegt daran, dass Material-Symbols im Hintergrund eine spezielle Schriftart sind, die mit den herkömmlichen CSS-Stylings für Schriften gestyled werden kann.
Infos zu den existierenden GIP-Color-Classes und dazu, wie du eigene CSS-Classes anlegst, findest du im Kapitel "Globaler CSS-Code".
Code des Beispiels
---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.MyCustomClass {
color: #FFAA3A;
border-width: 2px;
border-color: #7F0000;
border-style: dotted dashed solid double;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
html(raw(GIP_master({})) +
raw(GIP_layout({
uniqueId: "HorizontalBadge" + Nr,
embedded: false,
direction: "horizontal",
style: "gap: 8px;",
blocks: [{
value: GIP_layout({
uniqueId: "VerticalBadge1" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_badge({
uniqueId: "GIPColorPlain" + Nr,
embedded: true,
class: "GIPColorPlain",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorPlain"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorPurple" + Nr,
embedded: true,
class: "GIPColorPurple",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorPurple"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorBlue" + Nr,
embedded: true,
class: "GIPColorBlue",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorBlue"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorRed" + Nr,
embedded: true,
class: "GIPColorRed",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorRed"
}]
})
}]
})
}, {
value: GIP_layout({
uniqueId: "VerticalBadge2" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_badge({
uniqueId: "GIPColorGreen" + Nr,
embedded: true,
class: "GIPColorGreen",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorGreen"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorWhite" + Nr,
embedded: true,
class: "GIPColorWhite",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorWhite"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorNyan" + Nr,
embedded: true,
class: "GIPColorNyan",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorNyan"
}]
})
}, {
value: GIP_badge({
uniqueId: "MyCustomClass" + Nr,
embedded: true,
class: "MyCustomClass",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "MyCustomClass"
}]
})
}]
})
}]
})))---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.MyCustomClass {
color: #FFAA3A;
border-width: 2px;
border-color: #7F0000;
border-style: dotted dashed solid double;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
GIP_layout({
uniqueId: "HorizontalBadge" + Nr,
embedded: true,
direction: "horizontal",
style: "gap: 8px;",
blocks: [{
value: GIP_layout({
uniqueId: "VerticalBadge1" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_badge({
uniqueId: "GIPColorPlain" + Nr,
embedded: true,
class: "GIPColorPlain",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorPlain"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorPurple" + Nr,
embedded: true,
class: "GIPColorPurple",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorPurple"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorBlue" + Nr,
embedded: true,
class: "GIPColorBlue",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorBlue"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorRed" + Nr,
embedded: true,
class: "GIPColorRed",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorRed"
}]
})
}]
})
}, {
value: GIP_layout({
uniqueId: "VerticalBadge2" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_badge({
uniqueId: "GIPColorGreen" + Nr,
embedded: true,
class: "GIPColorGreen",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorGreen"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorWhite" + Nr,
embedded: true,
class: "GIPColorWhite",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorWhite"
}]
})
}, {
value: GIP_badge({
uniqueId: "GIPColorNyan" + Nr,
embedded: true,
class: "GIPColorNyan",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "GIPColorNyan"
}]
})
}, {
value: GIP_badge({
uniqueId: "MyCustomClass" + Nr,
embedded: true,
class: "MyCustomClass",
blocks: [{
value: GIP_materialSymbols({
icon: "spa"
})
}, {
value: "MyCustomClass"
}]
})
}]
})
}]
})Card
Card: Basis

Beschreibung
Wir möchten eine Card designen, um darin verschiedene Informationen strukturiert und ansprechend darzustellen. In diesem Beispiel sind dies Informationen zu einem Kater aus einem Tierheim. Wir nutzen die Blocks der Card, um die einzelnen Abschnitte unterschiedlich zu stylen. Hier verwenden wir den style-Key, aber dieses Styling könnte natürlich auch in Form von globalen CSS-Classes genutzt werden.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_card({
uniqueId: "Vermittlungskarte" + Nr,
embedded: false,
direction: "vertical",
class: "",
style: "background-color: #FFFCFA; border-color: #e5e2e0; padding: 25px; border-radius: 12px; color: #343a40; gap: 2px; justify-content: start;",
blocks: [{
class: "",
style: "font-size: 2.5em; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Simba"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Steckbrief —"
}, {
class: "",
style: "justify-content: start;",
value: "Fellfarbe: Rot, Getigert"
}, {
class: "",
style: "justify-content: start;",
value: "Alter: 4 Jahre"
}, {
class: "",
style: "justify-content: start;",
value: "Lieblingsspielzeug: Federangel"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Mehr über Simba —"
}, {
class: "",
style: "line-height: 1.6; text-align: justify; justify-content: start;",
value: "Unser Simba ist ein verschmuster und verspielter Kater, der die Welt mit neugierigen Augen erkundet. Er liebt gemütliche Nachmittage auf dem Sofa genauso wie ausgiebige Jagdspiele. Simba sucht ein liebevolles Zuhause, in dem er für immer ankommen darf."
}]
})))GIP_card({
uniqueId: "Vermittlungskarte" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "background-color: #FFFCFA; border-color: #e5e2e0; padding: 25px; border-radius: 12px; color: #343a40; gap: 2px; justify-content: start;",
blocks: [{
class: "",
style: "font-size: 2.5em; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Simba"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Steckbrief —"
}, {
class: "",
style: "justify-content: start;",
value: "Fellfarbe: Rot, Getigert"
}, {
class: "",
style: "justify-content: start;",
value: "Alter: 4 Jahre"
}, {
class: "",
style: "justify-content: start;",
value: "Lieblingsspielzeug: Federangel"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Mehr über Simba —"
}, {
class: "",
style: "line-height: 1.6; text-align: justify; justify-content: start;",
value: "Unser Simba ist ein verschmuster und verspielter Kater, der die Welt mit neugierigen Augen erkundet. Er liebt gemütliche Nachmittage auf dem Sofa genauso wie ausgiebige Jagdspiele. Simba sucht ein liebevolles Zuhause, in dem er für immer ankommen darf."
}]
})Card: Steckbrief mit Bild

Beschreibung
Wir möchten eine Card designen, um darin verschiedene Informationen strukturiert und ansprechend darzustellen. In diesem Beispiel sind dies Informationen zu einem Kater aus einem Tierheim. In den Blocks der Card übergeben wir verschiedene Texte und auch ein Image-Modul, um ein Bild des Katers darzustellen.
Image by: Amber Kipp via Unsplash
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_card({
uniqueId: "VermittlungskarteMitBild" + Nr,
embedded: false,
direction: "vertical",
class: "",
style: "background-color: #FFFCFA; border-color: #e5e2e0; padding: 25px; border-radius: 12px; color: #343a40; gap: 2px;",
blocks: [{
class: "",
style: "font-size: 2.5em; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Simba"
}, {
class: "",
style: "margin-top: 20px;",
value: GIP_image({
uniqueId: "Simba" + Nr,
embedded: true,
image: {
value: "https://images.unsplash.com/photo-1573865526739-10659fec78a5",
style: "width: 100%;"
}
})
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Steckbrief —"
}, {
class: "",
style: "justify-content: start;",
value: "Fellfarbe: Rot, Getigert"
}, {
class: "",
style: "justify-content: start;",
value: "Alter: 4 Jahre"
}, {
class: "",
style: "justify-content: start;",
value: "Lieblingsspielzeug: Federangel"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Mehr über Simba —"
}, {
class: "",
style: "line-height: 1.6; text-align: justify;",
value: "Unser Simba ist ein verschmuster und verspielter Kater, der die Welt mit neugierigen Augen erkundet. Er liebt gemütliche Nachmittage auf dem Sofa genauso wie ausgiebige Jagdspiele. Simba sucht ein liebevolles Zuhause, in dem er für immer ankommen darf."
}]
})))GIP_card({
uniqueId: "VermittlungskarteMitBild" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "background-color: #FFFCFA; border-color: #e5e2e0; padding: 25px; border-radius: 12px; color: #343a40; gap: 2px;",
blocks: [{
class: "",
style: "font-size: 2.5em; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Simba"
}, {
class: "",
style: "margin-top: 20px;",
value: GIP_image({
uniqueId: "Simba" + Nr,
embedded: true,
image: {
value: "https://images.unsplash.com/photo-1573865526739-10659fec78a5",
style: "width: 100%;"
}
})
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Steckbrief —"
}, {
class: "",
style: "justify-content: start;",
value: "Fellfarbe: Rot, Getigert"
}, {
class: "",
style: "justify-content: start;",
value: "Alter: 4 Jahre"
}, {
class: "",
style: "justify-content: start;",
value: "Lieblingsspielzeug: Federangel"
}, {
class: "",
style: "font-weight: bold; color: #6c757d; margin-top: 20px; margin-bottom: 5px; letter-spacing: 1px; text-transform: uppercase; justify-content: start;",
value: "— Mehr über Simba —"
}, {
class: "",
style: "line-height: 1.6; text-align: justify;",
value: "Unser Simba ist ein verschmuster und verspielter Kater, der die Welt mit neugierigen Augen erkundet. Er liebt gemütliche Nachmittage auf dem Sofa genauso wie ausgiebige Jagdspiele. Simba sucht ein liebevolles Zuhause, in dem er für immer ankommen darf."
}]
})Dialog
Dialog: Ohne weitere Module
Beschreibung
Wir möchten einen einfachen Dialog vom Typ Alert anzeigen, ohne dafür weitere GIP-Module zu nutzen.
Das Dialog-Element erhält zunächst die folgenden Werte:
let dialogId := "MeinDialog" + Nr;
GIP_dialog({
uniqueId: dialogId, //Die ID des Dialogs, mit dem wir ihn wieder aufrufen und öffnen können.
class: "",
style: "width: 300px; height: 100px; text-align: center; align-content: center;", //Größe des Dialogs und die Anordnung des Inhalts innerhalb des Dialogs.
value: "<p style='font-size: 20px; margin:0;'>Hallo Welt:</p><p style='font-size: 15px; margin:0;'>Dies ist ein Alert!</p>", //Text, der im Dialog angezeigt werden soll, mit zusätzlichem Inline-Styling.
showCloseButton: true, //true: Ein Button zum Schließen des Dialogs wird automatisch eingeblendet. false: Es wird kein Schließen-Button automatisch eingeblendet. In diesem Fall muss der Programmierer selbst einen Button zum Schließen für den Nutzer einbauen.
showAsModal: true //true: Der Dialog wird als Modal-Element angezeigt und blockiert Interaktion mit Ninox-Feldern im Hintergrund. false: Die Interaktion mit Ninox-Feldern im Hintergrund ist nicht blockiert.
})Als nächstes schreiben wir den HTML- und Javascript-Befehl, mit dem der Dialog aufgerufen werden soll. In diesem Beispiel haben wir ein Button-Element mit einer Click-Action gewählt:
<button id='ButtonOpenDialog' class='GIPColorBlue' style='border: none;' onclick='dialogFunction()'>Click me</button> //Button-Element mit Styling.
<script>
function dialogFunction() {
GIP.functions([{ //Aufruf der GIP-eigenen Functions, die in Elementen mit dem Actions-Key genutzt werden.
type: 'openGIPdialog',
dialogId: '" + replacex(text(dialogId), "[^\w-]", "") + "' //Ersetzten von Sonderzeichen in der Dialog-ID. Wenn die Dialog-ID keine Sonderzeichen enthält, kann die ID auch direkt angegeben werden.
}]);
}
</script>Code des Beispiels
let dialogId := "MeinDialog" + Nr;
html(raw(GIP_master({})) +
raw(GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 300px; height: 100px; text-align: center; align-content: center;",
value: "<p style='font-size: 20px; margin:0;'>Hallo Welt:</p><p style='font-size: 15px; margin:0;'>Dies ist ein Alert!</p>",
showCloseButton: true,
showAsModal: true
})) +
raw("<button id='ButtonOpenDialog' class='GIPColorBlue' style='border: none;' onclick='dialogFunction()'>Click me</button>
<script>
function dialogFunction() {
GIP.functions([{
type: 'openGIPdialog',
dialogId: '" +
replacex(text(dialogId), "[^\w-]", "") +
"'
}]);
}
</script>"))let dialogId := "MeinDialog" + Nr;
GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 300px; height: 100px; text-align: center; align-content: center;",
value: "<p style='font-size: 20px; margin:0;'>Hallo Welt:</p><p style='font-size: 15px; margin:0;'>Dies ist ein Alert!</p>",
showCloseButton: true,
showAsModal: true
}) +
raw("<button id='ButtonOpenDialog' class='GIPColorBlue' style='border: none;' onclick='dialogFunction()'>Click me</button>
<script>
function dialogFunction() {
GIP.functions([{
type: 'openGIPdialog',
dialogId: '" +
replacex(text(dialogId), "[^\w-]", "") +
"'
}]);
}
</script>")Dialog: Eingabemaske mit Form-ID
Beschreibung
Wir möchten eine Eingabemaske als Dialog erstellen, aus der die Daten erst in Ninox-Felder übernommen werden, wenn ein Button gedrückt wird.
Dazu legen wir zunächst einen Dialog an, in dem ein Text-Input und ein Number-Input liegen. Beide Input-Felder erhalten mit den Keys recordId und fieldId jeweils einen Verweis auf die Ninox-Felder, die geupdated werden sollen. Zusätzlich vergeben wir aber auch eine formId. Dadurch werden Werte, die in die Input-Felder eingetragen werden, zunächst im Session Storage zwischengespeichert.
Außerdem erhält unsere Eingabemaske einen Button, mit dem die Eingaben aus dem Session Storage in die Ninox-Eingabefelder übernommen werden sollen. Dies erreichen wir durch ein Action-Skript vom type "submitGIPform" und der Angabe der Form-ID.
let dialogId := "Eingabemaske" + Nr;
GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 400px; height: 300px;",
value: GIP_layout({
uniqueId: "InputFelder" + Nr,
direction: "vertical",
style: "width: auto; padding: 30px; height: auto;",
blocks: [{
style: "justify-content: center; color: #7F0000; font: bold 20px/3 arial; text-align: center;",
value: "Bitte Werte eingeben"
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Firma" + Nr,
inputType: "text",
recordId: Nr,
fieldId: fieldId(this, "Firmenname"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: Firmenname
},
title: {
style: "",
prefix: "Firma: "
},
placeholder: {
value: "Firmenname eingeben"
}
})
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Jaehrlicher Umsatz" + Nr,
inputType: "number",
recordId: Nr,
fieldId: fieldId(this, "Jährlicher Umsatz"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: number('Jährlicher Umsatz')
},
title: {
style: "",
suffix: " /a",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "USD",
minimumFractionDigits: 2
}
}
},
placeholder: {
style: "justify-content: flex-start;",
value: "Jahresumsatz eingeben"
}
})
}, {
style: "justify-content: center; padding-top: 20px;",
value: GIP_interaction({
uniqueId: "FormButton" + Nr,
direction: "horizontal",
class: "GIPColorBlue",
style: "height: 30px; width: 70%;",
blocks: [{
value: "Eingaben übernehmen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "submitGIPform",
formId: "MyForm"
}, {
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
})
}]
})
})Nun muss noch ein Element mit Actions gebaut werden, um unsere Eingabemaske zu öffnen. Dafür können alle GIP-Module mit dem Key actions verwendet werden, wir verwenden in diesem Beispiel ein Interaction-Element.
GIP_interaction({
uniqueId: "Button" + Nr,
class: "GIPColorBlue",
blocks: [{
value: "Öffne Dialog"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId,
showCloseButton: true,
showAsModal: true
}]
}]
})Code des Beispiels
let dialogId := "Eingabemaske" + Nr;
html(raw(GIP_master({})) +
raw(GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 400px; height: 300px;",
value: GIP_layout({
uniqueId: "InputFelder" + Nr,
direction: "vertical",
style: "width: auto; padding: 30px; height: auto;",
blocks: [{
style: "justify-content: center; color: #7F0000; font: bold 20px/3 arial; text-align: center;",
value: "Bitte Werte eingeben"
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Firma" + Nr,
inputType: "text",
recordId: Nr,
fieldId: fieldId(this, "Firmenname"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: Firmenname
},
title: {
style: "",
prefix: "Firma: "
},
placeholder: {
value: "Firmenname eingeben"
}
})
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Jaehrlicher Umsatz" + Nr,
inputType: "number",
recordId: Nr,
fieldId: fieldId(this, "Jährlicher Umsatz"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: number('Jährlicher Umsatz')
},
title: {
style: "",
suffix: " /a",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "USD",
minimumFractionDigits: 2
}
}
},
placeholder: {
style: "justify-content: flex-start;",
value: "Jahresumsatz eingeben"
}
})
}, {
style: "justify-content: center; padding-top: 20px;",
value: GIP_interaction({
uniqueId: "FormButton" + Nr,
direction: "horizontal",
class: "GIPColorBlue",
style: "height: 30px; width: 70%;",
blocks: [{
value: "Eingaben übernehmen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "submitGIPform",
formId: "MyForm"
}, {
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
})
}]
})
})) +
raw(GIP_interaction({
uniqueId: "Button" + Nr,
class: "GIPColorBlue",
blocks: [{
value: "Öffne Dialog"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId,
showCloseButton: true,
showAsModal: true
}]
}]
})))let dialogId := "Eingabemaske" + Nr;
raw(GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 400px; height: 300px;",
value: GIP_layout({
uniqueId: "InputFelder" + Nr,
direction: "vertical",
style: "width: auto; padding: 30px; height: auto;",
blocks: [{
style: "justify-content: center; color: #7F0000; font: bold 20px/3 arial; text-align: center;",
value: "Bitte Werte eingeben"
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Firma" + Nr,
inputType: "text",
recordId: Nr,
fieldId: fieldId(this, "Firmenname"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: Firmenname
},
title: {
style: "",
prefix: "Firma: "
},
placeholder: {
value: "Firmenname eingeben"
}
})
}, {
style: "justify-content: center;",
value: GIP_input({
uniqueId: "Jaehrlicher Umsatz" + Nr,
inputType: "number",
recordId: Nr,
fieldId: fieldId(this, "Jährlicher Umsatz"),
formId: "MyForm",
style: "width: 150px; height: 50px; align-items: center;",
fieldContent: {
value: number('Jährlicher Umsatz')
},
title: {
style: "",
suffix: " /a",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "USD",
minimumFractionDigits: 2
}
}
},
placeholder: {
style: "justify-content: flex-start;",
value: "Jahresumsatz eingeben"
}
})
}, {
style: "justify-content: center; padding-top: 20px;",
value: GIP_interaction({
uniqueId: "FormButton" + Nr,
direction: "horizontal",
class: "GIPColorBlue",
style: "height: 30px; width: 70%;",
blocks: [{
value: "Eingaben übernehmen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "submitGIPform",
formId: "MyForm"
}, {
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
})
}]
})
})) +
raw(GIP_interaction({
uniqueId: "Button" + Nr,
embedded: true,
class: "GIPColorBlue",
blocks: [{
value: "Öffne Dialog"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId,
showCloseButton: true,
showAsModal: true
}]
}]
}))Dialog: Sidebar-Menu
Beschreibung
Wir möchten ein Sidebar-Menu erstellen, dass beim Klicken auf einen Button am Rechten Bildschirmrand geöffnet wird.
Für den Inhalt des Menüs wird in diesem Beispiel ein Layout mit Text verwendet, aber es kommen auch alle anderen Module in Frage, z.B. Inputs, Selects oder Interactions. Dadurch kann diese Sidebar für das Setzen von Filtern, die Eingabe von Werten, zum anzeigen allgemeiner Infos und noch vielem mehr genutzt werden.
Das Dialog-Element muss für das gewünschte Verhalten ein besonderes Styling erhalten, das den Dialog:
- Vor dem Einblenden hinter dem rechten Bildschirmrand versteckt.
- Auf die komplette Bildschirmhöhe skaliert.
- Auf eine Breite skaliert, die sowohl am PC, als auch auf Smartphones eine sinnvolle Ansicht ergibt.
let dialogId := "SidebarMenu" + Nr;
GIP_dialog({
uniqueId: myDialogId,
class: "",
style: "transform: translateX(100%); transition: transform 0.3s ease-out; position: fixed; top: 0; right: 0; bottom: 0; left: auto; margin: 0; width: 80%; max-width: 500px; height: 100%; max-height: 100%; border-radius: 0;",
value: GIP_layout({
uniqueId: "DialogContent" + Nr,
embedded: true,
direction: "vertical",
style: "width: 100%; height: 100%; padding: 30px; gap: 20px;",
blocks: [{
style: "font-size: 22px; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Inhalt der Side-Bar"
}, {
style: "",
value: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. "
}, {
style: "",
value: "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
}]
}),
showCloseButton: true,
showAsModal: true
})Nun muss noch ein Element mit actions (in diesem Beispiel ein GIP-Interaction) gebaut werden, um unsere Sidebar anzuzeigen. Dafür müssen wir zwei Scripte schreiben: Das Öffnen des Dialogs und ein Custom Javascript, das den Dialogs hereingleiten zu lassen.
GIP_interaction({
uniqueId: "DialogOeffnen" + Nr,
embedded: false,
blocks: [{
style: "",
value: "Dialog öffnen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: myDialogId
}, {
type: "customJS",
value: "const myModalElement = document.getElementById('GIPDialog" + myDialogId +
"active');
setTimeout(() => {
myModalElement.style.transform = 'translateX(0)';
}, 10);
myModalElement.addEventListener('close', () => {
myModalElement.style.transform = 'translateX(100%)';
});"
}]
}]
})Code des Beispiels
let myDialogId := "SidebarMenu" + Nr;
html(raw(GIP_master({})) +
raw(GIP_dialog({
uniqueId: myDialogId,
class: "",
style: "transform: translateX(100%); transition: transform 0.3s ease-out; position: fixed; top: 0; right: 0; bottom: 0; left: auto; margin: 0; width: 80%; max-width: 500px; height: 100%; max-height: 100%; border-radius: 0;",
value: GIP_layout({
uniqueId: "DialogContent" + Nr,
embedded: true,
direction: "vertical",
style: "width: 100%; height: 100%; padding: 30px; gap: 20px;",
blocks: [{
style: "font-size: 22px; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Inhalt der Side-Bar"
}, {
style: "",
value: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. "
}, {
style: "",
value: "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
}]
}),
showCloseButton: true,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "DialogOeffnen" + Nr,
embedded: false,
blocks: [{
style: "",
value: "Dialog öffnen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: myDialogId
}, {
type: "customJS",
value: "const myModalElement = document.getElementById('GIPDialog" + myDialogId +
"active');
setTimeout(() => {
myModalElement.style.transform = 'translateX(0)';
}, 10);
myModalElement.addEventListener('close', () => {
myModalElement.style.transform = 'translateX(100%)';
});"
}]
}]
})))let myDialogId := "SidebarMenu" + Nr;
raw(GIP_dialog({
uniqueId: myDialogId,
class: "",
style: "transform: translateX(100%); transition: transform 0.3s ease-out; position: fixed; top: 0; right: 0; bottom: 0; left: auto; margin: 0; width: 80%; max-width: 500px; height: 100%; max-height: 100%; border-radius: 0;",
value: GIP_layout({
uniqueId: "DialogContent" + Nr,
embedded: true,
direction: "vertical",
style: "width: 100%; height: 100%; padding: 30px; gap: 20px;",
blocks: [{
style: "font-size: 22px; font-weight: bold; color: #e67e22; justify-content: start;",
value: "Inhalt der Side-Bar"
}, {
style: "",
value: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. "
}, {
style: "",
value: "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
}]
}),
showCloseButton: true,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "DialogOeffnen" + Nr,
embedded: true,
blocks: [{
style: "",
value: "Dialog öffnen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: myDialogId
}, {
type: "customJS",
value: "const myModalElement = document.getElementById('GIPDialog" + myDialogId +
"active');
setTimeout(() => {
myModalElement.style.transform = 'translateX(0)';
}, 10);
myModalElement.addEventListener('close', () => {
myModalElement.style.transform = 'translateX(100%)';
});"
}]
}]
}))Dialog: Video in Iframe
Beschreibung
Wir möchten eine Video-Anleitung in einen Dialog einbetten, damit Nutzer diese unkompliziert aufrufen können.
Der Aufruf des Dialogs erfolgt über ein GIP-Modul mit dem actions-Key, hier Beispielhaft ein Interaction-Element. Im Dialog selbst nutzen wir ein Layout, um zusätzlich zum Video noch einen alternativen Schließen-Button und eine Überschrift anzuordnen.
GIP_layout({
uniqueId: "VideoContainer" + Nr,
direction: "vertical",
style: "display: flex; flex-direction: column; height: 100%;",
blocks: [{
style: "justify-content: flex-end;",
value: GIP_materialSymbols({
filling: true,
scalingFactor: 1.3,
color: "#1F305E",
icon: "disabled_by_default"
}),
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
}, {
style: "justify-content: center; margin-bottom: 20px; color: #7F0000; font: bold 20px arial; text-align: center;",
value: "Verwendung des Moduls - Ausgangsrechnungen"
}]
})Damit nur dieser alternative Button verfügbar ist, setzen wir im Dialog showCloseButton auf false. Außerdem öffnen wir in diesem Beispiel den Dialog als modal, was aber optional ist.
GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 100%; height: 100%; max-width: 80vw; max-height: 80vh; padding: 20px 30px;",
value: GIP_layout({
uniqueId: "VideoContainer" + Nr,
direction: "vertical",
style: "display: flex; flex-direction: column; height: 100%;",
blocks: [{
style: "justify-content: flex-end;",
value: GIP_materialSymbols({
filling: true,
scalingFactor: 1.3,
color: "#1F305E",
icon: "disabled_by_default"
}),
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
}, {
style: "justify-content: center; margin-bottom: 20px; color: #7F0000; font: bold 20px arial; text-align: center;",
value: "Verwendung des Moduls - Ausgangsrechnungen"
}]
}),
showCloseButton: false,
showAsModal: true
})Um nun das Video im Dialog darzustellen, nutzen wir einen Iframe. In diesem Fall nutzen wir ein YouTube-Video und kopieren von dort den Iframe-Code. Zusätzlich fügen wir styling hinzu, um die Größe an den Dialog anzupassen. Den Iframe können wir danach einfach als value eines neuen Layout-Blocks übergeben.
GIP_layout({
uniqueId: "VideoContainer" + Nr,
direction: "vertical",
style: "display: flex; flex-direction: column; height: 100%;",
blocks: [{
style: "justify-content: flex-end;",
value: GIP_materialSymbols({
filling: true,
scalingFactor: 1.3,
color: "#1F305E",
icon: "disabled_by_default"
}),
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
}, {
style: "justify-content: center; margin-bottom: 20px; color: #7F0000; font: bold 20px arial; text-align: center;",
value: "Verwendung des Moduls - Ausgangsrechnungen"
}, {
style: "justify-content: center; align-items: center;",
value: ---
<iframe style="max-width: 100%; max-height: 800px; aspect-ratio: 16 / 9;" src="https://www.youtube.com/embed/hYQCYr7Y19w?si=lqLT9Gd5y9DaUJk-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
---
}]
})Code des Beispiels
let dialogId := "DialogMitVideoanleitung" + Nr;
html(raw(GIP_master({})) +
raw(GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 100%; height: 100%; max-width: 80vw; max-height: 80vh; padding: 20px 30px;",
value: GIP_layout({
uniqueId: "VideoContainer" + Nr,
direction: "vertical",
style: "display: flex; flex-direction: column; height: 100%;",
blocks: [{
style: "justify-content: flex-end;",
value: GIP_materialSymbols({
filling: true,
scalingFactor: 1.3,
color: "#1F305E",
icon: "disabled_by_default"
}),
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
}, {
style: "justify-content: center; margin-bottom: 20px; color: #7F0000; font: bold 20px arial; text-align: center;",
value: "Verwendung des Moduls - Ausgangsrechnungen"
}, {
style: "justify-content: center; align-items: center;",
value: ---
<iframe style="max-width: 100%; max-height: 800px; aspect-ratio: 16 / 9;" src="https://www.youtube.com/embed/hYQCYr7Y19w?si=lqLT9Gd5y9DaUJk-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
---
}]
}),
showCloseButton: false,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "ButtonFürVideoanleitung" + Nr,
class: "GIPColorBlue",
blocks: [{
value: "Öffne Video-Anleitung"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId
}]
}]
})))let dialogId := "DialogMitVideoanleitung" + Nr;
raw(GIP_dialog({
uniqueId: dialogId,
class: "",
style: "width: 100%; height: 100%; max-width: 80vw; max-height: 80vh; padding: 20px 30px;",
value: GIP_layout({
uniqueId: "VideoContainer" + Nr,
direction: "vertical",
style: "display: flex; flex-direction: column; height: 100%;",
blocks: [{
style: "justify-content: flex-end;",
value: GIP_materialSymbols({
filling: true,
scalingFactor: 1.3,
color: "#1F305E",
icon: "disabled_by_default"
}),
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
}, {
style: "justify-content: center; margin-bottom: 20px; color: #7F0000; font: bold 20px arial; text-align: center;",
value: "Verwendung des Moduls - Ausgangsrechnungen"
}, {
style: "justify-content: center; align-items: center;",
value: ---
<iframe style="max-width: 100%; max-height: 800px; aspect-ratio: 16 / 9;" src="https://www.youtube.com/embed/hYQCYr7Y19w?si=lqLT9Gd5y9DaUJk-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
---
}]
}),
showCloseButton: false,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "ButtonFürVideoanleitung" + Nr,
embedded: true
class: "GIPColorBlue",
blocks: [{
value: "Öffne Video-Anleitung"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId
}]
}]
}))Globaler CSS-Code
CSS-Classes: Global Corporate Design anlegen
Beschreibung
Wir möchten unser Corporate Design global anlegen, um es überall in unserer Datenbank für Module nutzen zu können. Dafür fügen wir den folgenden CSS-Code in der globalen Ninox-Funktion GIP_customCSS() ein und laden Ninox neu (STRG + F5 drücken):
.CompanyButton {
background-color: #e5f1ff;
border-color: #003e8d;
color: #003e8d
}
.CompanyBadge {
background-color: #ffe9cc;
border-color: #ff9b2c;
color: #ff9b2c;
width: 100px;
height: 30px;
font-size: 12px;
border-radius: 15px;
}
.CompanyDialog {
border-color: #ff9b2c;
color: #522e00;
width: 400px;
height: 270px;
}Mit diesen Classes können wir nun überall in unserer Datenbank die entsprechenden Module stylen.
Code des Beispiels
---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.CompanyButton {
background-color: #e5f1ff;
border-color: #003e8d;
color: #003e8d
}
.CompanyBadge {
background-color: #ffe9cc;
border-color: #ff9b2c;
color: #ff9b2c;
width: 100px;
height: 30px;
font-size: 12px;
border-radius: 15px;
}
.CompanyDialog {
border-color: #ff9b2c;
color: #522e00;
width: 400px;
height: 270px;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
let dialogId := "MeinDialog" + Nr;
html(raw(GIP_master({})) +
raw(GIP_dialog({
uniqueId: dialogId,
class: "CompanyDialog",
style: "padding: 30px",
value: GIP_layout({
uniqueId: "Layout" + Nr,
embedded: true,
direction: "vertical",
style: "height: 100%;",
blocks: [{
style: "justify-content: center;",
value: GIP_interaction({
uniqueId: "Badge" + Nr,
embedded: true,
class: "CompanyBadge",
blocks: [{
value: "MyCompany"
}]
})
}, {
style: "height: 190px;",
value: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
}, {
value: GIP_interaction({
uniqueId: "Button" + Nr,
embedded: true,
class: "CompanyButton",
blocks: [{
value: "Schließe Dialog"
}],
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
})
}]
}),
showCloseButton: true,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "OpenDialog" + Nr,
embedded: false,
blocks: [{
value: "Öffne Dialog als Beispiel"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId
}]
}]
})))---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.CompanyButton {
background-color: #e5f1ff;
border-color: #003e8d;
color: #003e8d
}
.CompanyBadge {
background-color: #ffe9cc;
border-color: #ff9b2c;
color: #ff9b2c;
width: 100px;
height: 30px;
font-size: 12px;
border-radius: 15px;
}
.CompanyDialog {
border-color: #ff9b2c;
color: #522e00;
width: 400px;
height: 270px;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
let dialogId := "MeinDialog" + Nr;
GIP_dialog({
uniqueId: dialogId,
class: "CompanyDialog",
style: "padding: 30px",
value: GIP_layout({
uniqueId: "Layout" + Nr,
embedded: true,
direction: "vertical",
style: "height: 100%;",
blocks: [{
style: "justify-content: center;",
value: GIP_interaction({
uniqueId: "Badge" + Nr,
embedded: true,
class: "CompanyBadge",
blocks: [{
value: "MyCompany"
}]
})
}, {
style: "height: 190px;",
value: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
}, {
value: GIP_interaction({
uniqueId: "Button" + Nr,
embedded: true,
class: "CompanyButton",
blocks: [{
value: "Schließe Dialog"
}],
actions: [{
trigger: "click",
scripts: [{
type: "closeGIPdialog",
dialogId: dialogId
}]
}]
})
}]
}),
showCloseButton: true,
showAsModal: true
})) +
raw(GIP_interaction({
uniqueId: "OpenDialog" + Nr,
embedded: true,
blocks: [{
value: "Öffne Dialog als Beispiel"
}],
actions: [{
trigger: "click",
scripts: [{
type: "openGIPdialog",
dialogId: dialogId
}]
}]
}))Grid
Grid: Basis Horizontal
Beschreibung
Wir möchten ein horizontales Grid erstellen, dass eine Track-Breite, also eine Spaltenbreite, von mindestens 150px und maximal 1fr hat. Das Grid soll automatisch so viele Tracks wie möglich pro Zeile erzeugen und automatisch in die nächste Zeile umbrechen.
Für diese Anforderung können wir größtenteils die Default-Einstellungen des Grids nutzen. Dort ist für die Tracks, also Spalten des Grids, eine Breite zwischen 150px und 1fr festgelegt durch minmax(150px, 1fr). Zusätzlich sagt repeat(auto-fit, ...), dass wir so viele Spalten wie möglich mit dieser Spaltenbreite pro Zeile erzeugen wollen. Für die Zeilen ist mit auto-flow definiert, dass diese automatisch erzeugt werden sollen.
grid: auto-flow / repeat(auto-fit, minmax(150px, 1fr));Wir vergeben zusätzliche eine Höhe für das Grid. Wenn mehr Zeilen erzeugt werden, als in diese Höhe passen, wird das Grid scrollbar. Als Inhalt der Grid-Blöcke wird hier beispielhaft das GIP-Card-Modul verwendet.
Code des Beispiels
let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
let data := {
uniqueId: "Basis Horizontal" + Nr,
embedded: false,
direction: "horizontal",
class: "",
style: "height: 900px;",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
};
html(raw(GIP_master({})) + raw(GIP_grid(data)))let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
GIP_grid({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "horizontal",
class: "",
style: "height: 900px;",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
})Grid: Basis Vertikal
Beschreibung
Wir möchten ein vertikales Grid erstellen, dass eine Track-Weite, also eine Zeilenhöhe, von mindestens 150px und maximal 1fr hat. Das Grid soll automatisch so viele Tracks wie möglich pro Spalte erzeugen und automatisch in die nächste Spalte umbrechen.
Für diese Anforderung können wir größtenteils die Default-Einstellungen des Grids nutzen. Dort ist für die Tracks, also Zeilen des Grids, eine Höhe zwischen 150px und 1fr festgelegt durch minmax(150px, 1fr). Zusätzlich sagt repeat(auto-fit, ...), dass wir so viele Zeilen wie möglich mit dieser Zeilenhöhe pro Spalte erzeugen wollen. Für die Spalten ist mit auto-flow definiert, dass diese automatisch erzeugt werden sollen.
grid: repeat(auto-fit, minmax(150px, 1fr)) / auto-flow;Die Höhe des Ninox-Formelfeldes schrumpft durch embedded: false in diesem Beispiel immer auf die Track-Höhe zusammen. In einem Praxisbeispiel würde man entweder eine feste Höhe für das Grid vergeben oder es in einem Container einbetten, dessen Höhe variiert werden kann. Als Inhalt der Grid-Blöcke wird hier beispielhaft das GIP-Card-Modul verwendet.
Code des Beispiels
let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
let data := {
uniqueId: "Basis Horizontal" + Nr,
embedded: false,
direction: "vertical",
class: "",
style: "",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "height: 100%; width: 150px;",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
};
html(raw(GIP_master({})) + raw(GIP_grid(data)))let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
GIP_grid({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Basis Horizontal" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "height: 100%; width: 150px;",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
})Grid: Track-Anzahl und -Weite

Beschreibung
Wir möchten ein Grid erstellen, in dem wir 5 Tracks mit jeweils einer Breite von 200px haben.
Die Anzahl der Tracks übergeben wir mit gridTrackCount: 5 und die Breite (Weite) der Tracks mit gridTrackSize: "200px". Diese Angaben werden vom GIP-Grid zu folgendem CSS-Ausdruck umgebaut:
grid: auto-flow / repeat(5, 200px);Mit diesem Styling platziert das Grid in jeder Zeile 5 Blöcke mit je 200px Breite. Sollte die zur Verfügung stehende Breite nicht ausreichen, wird das Grid scrollbar.
Code des Beispiels
let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
let data := {
uniqueId: "Fixed Tracks" + Nr,
embedded: false,
direction: "horizontal",
gridTrackCount: 5,
gridTrackSize: "200px",
class: "",
style: "height: 900px;",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Fixed Tracks" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
};
html(raw(GIP_master({})) + raw(GIP_grid(data)))let speedTestData := ((select '4. Data for Speedtest' where number(Nr) < 20) order by -number(Nr));
GIP_grid({
uniqueId: "Fixed Tracks" + Nr,
embedded: true,
direction: "horizontal",
gridTrackCount: 5,
gridTrackSize: "200px",
class: "",
style: "height: 900px;",
blocks: speedTestData.{
class: "",
style: "",
value: GIP_card({
uniqueId: "Fixed Tracks" + Nr,
embedded: true,
direction: "vertical",
class: "",
style: "",
blocks: [{
style: "",
value: GIP_materialSymbols({
icon: "spa"
})
}, {
style: "",
value: 'Input Text 1'
}],
actions: [{
trigger: "click",
scripts: [{
type: "popupRecord",
recordId: raw(Nr)
}]
}]
})
}
})Image
Image: Bild mit Überschrift

Beschreibung
Wir möchten ein Bild mit einer Überschrift darüber anzeigen. Das Bild soll eine feste Breite haben.
Zuerst definieren wir das image-Objekt mit der URL und einem style, um die Breite zu begrenzen. Dann fügen wir ein label hinzu und setzen den Text (value). Die orientation ist standardmäßig 'top', also müssen wir sie nicht explizit setzen.
Image by: Amber Kipp via Unsplash
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_image({
uniqueId: "Beispielbild" + Nr,
embedded: false,
image: {
value: "https://images.unsplash.com/photo-1573865526739-10659fec78a5",
style: "width: 300px;"
},
label: {
value: "Eine orange Katze",
style: "font-size: 1.2em; font-weight: bold; padding-bottom: 10px;"
}
})))GIP_image({
uniqueId: "Beispielbild" + Nr,
embedded: true,
image: {
value: "https://images.unsplash.com/photo-1573865526739-10659fec78a5",
style: "width: 300px;"
},
label: {
value: "Eine orange Katze",
style: "font-size: 1.2em; font-weight: bold; padding-bottom: 10px;"
}
})Input
Input: Einzeiliger Text
Beschreibung
Wir möchten ein einzeiliges Textfeld erstellen, das den eingegebenen Text in ein normales Ninox-Textfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Einzeiliger Text" + Nr,
embedded: false,
inputType: "text", //Eingabetyp für eine einzeilige Texteingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Textfeld liegt.
fieldId: fieldId(this, "Text") //Field-ID des Ninox-Textfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Als nächstes definieren wir unseren Field Content. Wir möchten hierfür immer denselben Wert anzeigen, der im Textfeld steht, und referenzieren daher im Value das Ninox-Textfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe, aber sparen uns die Definition des Values. Wenn kein Value für den Title angeben ist, wird als Default des Titles der Field Content gewählt.
Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll.
GIP_input({
uniqueId: "Einzeiliger Text" + Nr,
embedded: false,
inputType: "text",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;"
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: Text
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Text eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red;",
value: "Inputfeld Text",
orientation: "top"
}
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Einzeiliger Text" + Nr,
embedded: false,
inputType: "text",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text"),
title: {
style: "color: orange;"
},
fieldContent: {
style: "color: blue;",
value: Text
},
placeholder: {
style: "font-style: italic;",
value: "Text eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Text",
orientation: "top"
}
})
))GIP_input({
uniqueId: "Einzeiliger Text" + Nr,
embedded: true,
inputType: "text",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text"),
title: {
style: "color: orange;"
},
fieldContent: {
style: "color: blue;",
value: Text
},
placeholder: {
style: "font-style: italic;",
value: "Text eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Text",
orientation: "top"
}
})Input: Mehrzeiliger Text
Beschreibung
Wir möchten ein mehrzeiliges Textfeld erstellen, das den eingegebenen Text in ein mehrzeiliges Ninox-Textfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Mehrzeiliger Text" + Nr,
embedded: false,
inputType: "textarea", //Eingabetyp für eine mehrzeilige Texteingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Textfeld liegt.
fieldId: fieldId(this, "Text (mehrzeilig)") //Field-ID des Ninox-Textfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Die Höhe der Textarea skaliert automatisch mit der Menge des eingegebenen Textes. Wenn wir eine feste Höhe haben möchten, sodass das Textfeld bei überlaufendem Inhalt scrollbar wird, können wir z.B. style: "height: 150px;" definieren.
Nun ist noch der tatsächliche Inhalt des Input-Elementes festzulegen. Als erstes definieren wir unseren Field Content. Wir möchten hierfür immer denselben Wert anzeigen, der im mehrzeiligen Textfeld steht, und referenzieren daher im Value das Ninox-Textfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe, aber sparen uns die Definition des Values. Wenn kein Value für den Title angeben ist, wird als Default des Titles der Field Content gewählt.
Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll.
GIP_input({
uniqueId: "Mehrzeiliger Text" + Nr,
embedded: false,
inputType: "textarea",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text (mehrzeilig)"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;"
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: 'Text (mehrzeilig)'
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Mehrzeiligen Text eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red;",
value: "Inputfeld Textarea",
orientation: "top"
}
})Standardmäßig ist in Textfeldern ein Spellcheck aktiviert, der auf den Browser-Einstellungen für die Sprache basiert. Möchte man diesen Spellcheck in Input-Elementen deaktivieren, fügt man folgende Code-Zeile ein:
GIP_input({
uniqueId: "Mehrzeiliger Text" + Nr,
embedded: false,
inputType: "textarea",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text (mehrzeilig)"),
htmlAttribute: "spellcheck='false'"
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Mehrzeiliger Text" + Nr,
embedded: false,
inputType: "textarea",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text (mehrzeilig)"),
title: {
style: "color: orange;"
},
fieldContent: {
style: "color: blue;",
value: 'Text (mehrzeilig)'
},
placeholder: {
style: "font-style: italic;",
value: "Mehrzeiligen Text eingeben"
},
label: {
class: "",
style: "color: red;",
value: "Inputfeld Textarea",
orientation: "top"
}
})
))GIP_input({
uniqueId: "Mehrzeiliger Text" + Nr,
embedded: true,
inputType: "textarea",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Text (mehrzeilig)"),
title: {
style: "color: orange;"
},
fieldContent: {
style: "color: blue;",
value: 'Text (mehrzeilig)'
},
placeholder: {
style: "font-style: italic;",
value: "Mehrzeiligen Text eingeben"
},
label: {
class: "",
style: "color: red;",
value: "Inputfeld Textarea",
orientation: "top"
}
})Input: Zahl
Beschreibung
Wir möchten ein Zahlfeld erstellen, das die eingegebene Zahl in ein Ninox-Zahlfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Zahl" + Nr,
embedded: false,
inputType: "number", //Eingabetyp für eine Zahleingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Zahlfeld liegt.
fieldId: fieldId(this, "Zahl") //Field-ID des Ninox-Zahlfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Wir möchten den Text, bzw. die Zahl im Eingabefeld rechtsbündig darstellen. Daher legen wir den Style des kompletten Input-Elementes in folgender Form fest: style: "justify-content: flex-end;".
Nun ist noch der tatsächliche Inhalt des Input-Elementes festzulegen. Als erstes definieren wir unseren Field Content. Wir möchten hierfür immer den reinen Zahlwert anzeigen, der im Zahlfeld steht, und referenzieren daher im Value das Ninox-Zahlfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe. Den Wert des Titles beziehen wir ebenfalls auf das Ninox-Zahlfeld, aber wir wollen hier nicht nur den Zahlwert, sondern die Zahl mit der im Ninox-Zahlfeld festgelegten Formatierung anzeigen. Daher legen wir für den Title value: text(Zahl) fest. Wenn kein Value für den Title angeben ist, wird als Default des Titles der Field Content gewählt.
Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll, in diesem Fall links.
GIP_input({
uniqueId: "Zahl" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;",
value: text(Zahl)
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: Zahl
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red; width: 30px;",
value: "Inputfeld Zahl",
orientation: "left"
}
})Zusätzlich möchten wir auf Mobilgeräten bei der Eingabe im Zahlfeld automatisch den Nummernblock statt der normalen Tastatur angezeigt bekommen. Dafür fügen wir folgende Code-Zeile ein:
GIP_input({
uniqueId: "Zahl" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text(Zahl)
},
fieldContent: {
style: "color: blue;",
value: Zahl
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red; width: 30px;",
value: "Inputfeld Zahl",
orientation: "left"
}
})Ansicht mit Field Content und Nummernblock auf Mobilgerät
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Zahl" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text(Zahl)
},
fieldContent: {
style: "color: blue;",
value: Zahl
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red; width: 90px;",
value: "Inputfeld Zahl",
orientation: "left"
}
})
))GIP_input({
uniqueId: "Zahl" + Nr,
embedded: true,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text(Zahl)
},
fieldContent: {
style: "color: blue;",
value: Zahl
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red; width: 90px;",
value: "Inputfeld Zahl",
orientation: "left"
}
})Input: Zahl mit Präfix
Beschreibung
Wir möchten ein Zahlfeld erstellen, das die eingegebene Zahl in ein Ninox-Zahlfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Zahl mit Präfix" + Nr,
embedded: false,
inputType: "number", //Eingabetyp für eine Zahleingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Zahlfeld liegt.
fieldId: fieldId(this, "Zahl mit Präfix") //Field-ID des Ninox-Zahlfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Wir möchten den Text, bzw. die Zahl im Eingabefeld rechtsbündig darstellen. Daher legen wir den Style des kompletten Input-Elementes in folgender Form fest: style: "justify-content: flex-end;".
Nun ist noch der tatsächliche Inhalt des Input-Elementes festzulegen. Als erstes definieren wir unseren Field Content. Wir möchten hierfür immer den reinen Zahlwert anzeigen, der im Zahlfeld steht, und referenzieren daher im Value das Ninox-Zahlfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe. Den Wert des Titles beziehen wir ebenfalls auf das Ninox-Zahlfeld, aber wir wollen hier nicht nur den Zahlwert, sondern die Zahl mit der im Ninox-Zahlfeld festgelegten Formatierung anzeigen. Daher legen wir für den Title value: text('Zahl mit Präfix') fest. Wenn kein Value für den Title angeben ist, wird als Default des Titles der Field Content gewählt. Zusätzlich möchten wir vor dem formatierten Zahlwert den Text "Summe (netto): " anzeigen und geben daher dem Title einen Präfix in folgender Form: prefix: "Summe (netto): ".
Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll.
GIP_input({
uniqueId: "Zahl mit Präfix" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl mit Präfix"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;",
value: text('Zahl mit Präfix'),
prefix: "Summe (netto): "
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: 'Zahl mit Präfix'
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red; width: 30px;",
value: "Inputfeld Zahl mit Präfix",
orientation: "top"
}
})Zusätzlich möchten wir auf Mobilgeräten bei der Eingabe im Zahlfeld automatisch den Nummernblock statt der normalen Tastatur angezeigt bekommen. Dafür fügen wir folgende Code-Zeile ein:
GIP_input({
uniqueId: "Zahl mit Präfix" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl mit Präfix"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text('Zahl mit Präfix'),
prefix: "Summe (netto): "
},
fieldContent: {
style: "color: blue;",
value: 'Zahl mit Präfix'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red; width: 30px;",
value: "Inputfeld Zahl mit Präfix",
orientation: "left"
}
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Zahl mit Präfix" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl mit Präfix"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text('Zahl mit Präfix'),
prefix: "Summe (netto): "
},
fieldContent: {
style: "color: blue;",
value: 'Zahl mit Präfix'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl mit Präfix",
orientation: "top"
}
})
))GIP_input({
uniqueId: "Zahl mit Präfix" + Nr,
embedded: true,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl mit Präfix"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
value: text('Zahl mit Präfix'),
prefix: "Summe (netto): "
},
fieldContent: {
style: "color: blue;",
value: 'Zahl mit Präfix'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl mit Präfix",
orientation: "top"
}
})Input: Zahl mit "basic"-Format
Beschreibung
Wir möchten ein Zahlfeld erstellen, das die eingegebene Zahl in ein Ninox-Zahlfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: false,
inputType: "number", //Eingabetyp für eine Zahleingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Zahlfeld liegt.
fieldId: fieldId(this, "Zahl 'Basic' formatiert") //Field-ID des Ninox-Zahlfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Wir möchten den Text, bzw. die Zahl im Eingabefeld rechtsbündig darstellen. Daher legen wir den Style des kompletten Input-Elementes in folgender Form fest: style: "justify-content: flex-end;".
Nun ist noch der tatsächliche Inhalt des Input-Elementes festzulegen. Als erstes definieren wir unseren Field Content. Wir möchten hierfür immer den reinen Zahlwert anzeigen, der im Zahlfeld steht, und referenzieren daher im Value das Ninox-Zahlfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe. Als Title wollen wir den Zahlwert des Ninox-Zahlfeldes mit einer von uns festgelegten Formatierung anzeigen. Da wir den Zahlwert bereits an den Field Content übergeben, müssen wir keinen Value für den Title angeben, sondern nur die Formatierung. Wir wählen in diesem Fall den Formattyp "basic" mit den folgenden Optionen:
- Wir möchten 3 Dezimalstellen ("Nachkommastellen") haben
- Statt einem Komma soll unser Dezimaltrenner ein Punkt sein
- Die Separatorstellen ("Tausenderstellen") wollen wir nicht in drei Ziffern, sondern 2 Ziffern zwischen jedem Trennzeichen aufteilen
- Statt einem Punkt soll unser Separator ("Tausendertrenner") das Rauten-Symbol sein
GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Basic' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "basic",
decimalDigits: "3",
decimalSign: ".",
separatorDigits: "2",
separatorSign: "#"
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Basic'' formatiert'
}
})
))Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll.
GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Basic' formatiert"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;",
numberFormat: {
formatType: "basic",
decimalDigits: "3",
decimalSign: ".",
separatorDigits: "2",
separatorSign: "#"
}
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: 'Zahl ''Basic'' formatiert'
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red;",
value: "Inputfeld Zahl 'Basic' formatiert",
orientation: "top"
}
})Zusätzlich möchten wir auf Mobilgeräten bei der Eingabe im Zahlfeld automatisch den Nummernblock statt der normalen Tastatur angezeigt bekommen. Dafür fügen wir folgende Code-Zeile ein:
GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Basic' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "basic",
decimalDigits: "3",
decimalSign: ".",
separatorDigits: "2",
separatorSign: "#"
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Basic'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Basic' formatiert",
orientation: "top"
}
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Basic' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "basic",
decimalDigits: "3",
decimalSign: ".",
separatorDigits: "2",
separatorSign: "#"
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Basic'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Basic' formatiert",
orientation: "top"
}
})
))GIP_input({
uniqueId: "Zahl basic formatiert" + Nr,
embedded: true,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Basic' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "basic",
decimalDigits: "3",
decimalSign: ".",
separatorDigits: "2",
separatorSign: "#"
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Basic'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Basic' formatiert",
orientation: "top"
}
})Input: Zahl mit "intl"-Format
Beschreibung
Wir möchten ein Zahlfeld erstellen, das die eingegebene Zahl in ein Ninox-Zahlfeld schreibt.
Wir geben dem Input-Element zunächst die folgenden Werte:
GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: false,
inputType: "number", //Eingabetyp für eine Zahleingabe
contentEditable: true, //true: Der Nutzer kann den Wert im Input-Element bearbeiten. false: Eine Eingabe ins Input-Element ist nicht möglich.
recordId: Nr, //Record-ID der Ninox-Tabelle, in der das Ninox-Zahlfeld liegt.
fieldId: fieldId(this, "Zahl 'Intl' formatiert") //Field-ID des Ninox-Zahlfeldes. Die hier genutzte Ninox-Funktion "fieldId" kann auch durch die Field-ID als String ersetzt werden, z.B. "N".
})Wir möchten den Text, bzw. die Zahl im Eingabefeld rechtsbündig darstellen. Daher legen wir den Style des kompletten Input-Elementes in folgender Form fest: style: "justify-content: flex-end;".
Nun ist noch der tatsächliche Inhalt des Input-Elementes festzulegen. Als erstes definieren wir unseren Field Content. Wir möchten hierfür immer den reinen Zahlwert anzeigen, der im Zahlfeld steht, und referenzieren daher im Value das Ninox-Zahlfeld. Als Style vergeben wir eine orange Schriftfarbe.
Unserem Title geben wir als Style eine blaue Schriftfarbe. Als Title wollen wir den Zahlwert des Ninox-Zahlfeldes mit einer von uns festgelegten Formatierung anzeigen. Da wir den Zahlwert bereits an den Field Content übergeben, müssen wir keinen Value für den Title angeben, sondern nur die Formatierung. Wir wählen in diesem Fall den Formattyp "intl" mit den folgenden Optionen:
- Durch die Angabe
locale: "en-IN"erhalten wir die für Indien ländertypische Zahlenformatierung bezüglich Dezimalstellen und -trenner sowie Separatorstellen und -trenner - Der Zahlwert soll in der Währung Euro dargestellt werden
GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Intl' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "EUR"
}
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Intl'' formatiert'
}
})
))Der Placeholder erhält einen statischen Text, der immer bei fehlendem Input angezeigt werden soll, und den Style Italic. Die Standard-Schriftfarbe für den Placeholder ist Grau.
Zuletzt geben wir auch dem Label eine Schriftfarbe, in diesem Fall Rot, und ebenfalls einen statischen Text als Wert. Zusätzlich geben wir außerdem noch an, wo das Label im Verhältnis zum Eingabefeld angezeigt werden soll.
GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Intl' formatiert"),
title: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt.
style: "color: orange;",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "EUR"
}
}
},
fieldContent: { //Wird angezeigt, sobald der Nutzer ins Eingabefeld klickt und wird durch seine Eingabe verändert.
style: "color: blue;",
value: 'Zahl ''Intl'' formatiert'
},
placeholder: { //Wird angezeigt, bevor der Nutzer ins Eingabefeld klickt und wenn der Field Content leer ist.
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: { //Das Label wird über, unter oder neben (links/rechts) dem Eingabefeld angezeigt.
style: "color: red;",
value: "Inputfeld Zahl 'Intl' formatiert",
orientation: "top"
}
})Zusätzlich möchten wir auf Mobilgeräten bei der Eingabe im Zahlfeld automatisch den Nummernblock statt der normalen Tastatur angezeigt bekommen. Dafür fügen wir folgende Code-Zeile ein:
GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Intl' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "EUR"
}
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Intl'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Intl' formatiert",
orientation: "top"
}
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: false,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Intl' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "EUR"
}
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Intl'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Intl' formatiert",
orientation: "top"
}
})
))GIP_input({
uniqueId: "Zahl intl formatiert" + Nr,
embedded: true,
style: "justify-content: flex-end;",
inputType: "number",
contentEditable: true,
recordId: Nr,
fieldId: fieldId(this, "Zahl 'Intl' formatiert"),
htmlAttribute: "inputmode='numeric'",
title: {
style: "color: orange;",
numberFormat: {
formatType: "intl",
locale: "en-IN",
options: {
style: "currency",
currency: "EUR"
}
}
},
fieldContent: {
style: "color: blue;",
value: 'Zahl ''Intl'' formatiert'
},
placeholder: {
style: "font-style: italic;",
value: "Zahl eingeben"
},
label: {
style: "color: red;",
value: "Inputfeld Zahl 'Intl' formatiert",
orientation: "top"
}
})Input: Datum
Beschreibung
Wir möchten ein Input-Feld erstellen, mit dem wir ein Ninox-Datum-Feld beschreiben können.
Dafür legen wir als inputType den Wert "date" fest und stellen unsere restlichen Konfigurationen wie gewohnt ein. Den value von fieldContent müssen wir dabei als raw(Datum) übergeben.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Date" + Nr,
embedded: false,
contentEditable: true,
inputType: "date",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Datum"),
label: {
style: "color: orange",
value: "Datum",
orientation: "top"
},
fieldContent: {
value: raw(Datum)
},
placeholder: {
value: "Datum eingeben"
}
})
))GIP_input({
uniqueId: "Date" + Nr,
embedded: true,
contentEditable: true,
inputType: "date",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Datum"),
label: {
style: "color: orange",
value: "Datum",
orientation: "top"
},
fieldContent: {
value: raw(Datum)
},
placeholder: {
value: "Datum eingeben"
}
})Input: Uhrzeit
Beschreibung
Wir möchten ein Input-Feld erstellen, mit dem wir ein Ninox-Uhrzeit-Feld beschreiben können.
Dafür legen wir als inputType den Wert "time" fest und stellen unsere restlichen Konfigurationen wie gewohnt ein. Den value von fieldContent müssen wir dabei als raw(Uhrzeit) übergeben.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Time" + Nr,
embedded: false,
contentEditable: true,
inputType: "time",
style: "",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Uhrzeit"),
label: {
style: "color: orange",
value: "Uhrzeit",
orientation: "top"
},
fieldContent: {
value: raw(Uhrzeit)
},
placeholder: {
value: "Uhrzeit eingeben"
}
})
))GIP_input({
uniqueId: "Time" + Nr,
embedded: true,
contentEditable: true,
inputType: "time",
style: "",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Uhrzeit"),
label: {
style: "color: orange",
value: "Uhrzeit",
orientation: "top"
},
fieldContent: {
value: raw(Uhrzeit)
},
placeholder: {
value: "Uhrzeit eingeben"
}
})Input: Datum + Uhrzeit
Beschreibung
Wir möchten ein Input-Feld erstellen, mit dem wir ein Ninox-Feld für Datum + Uhrzeit beschreiben können.
Dafür legen wir als inputType den Wert "datetime" fest und stellen unsere restlichen Konfigurationen wie gewohnt ein. Den value von fieldContent müssen wir dabei als raw('Datum + Uhrzeit') übergeben.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "DateTime" + Nr,
embedded: false,
contentEditable: true,
inputType: "datetime",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Datum + Uhrzeit"),
label: {
style: "color: orange",
value: "Datum und Uhrzeit",
orientation: "top"
},
fieldContent: {
value: raw('Datum + Uhrzeit')
},
placeholder: {
value: "Datum + Uhrzeit eingeben"
}
})))GIP_input({
uniqueId: "DateTime" + Nr,
embedded: true,
contentEditable: true,
inputType: "datetime",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Datum + Uhrzeit"),
label: {
style: "color: orange",
value: "Datum und Uhrzeit",
orientation: "top"
},
fieldContent: {
value: raw('Datum + Uhrzeit')
},
placeholder: {
value: "Datum + Uhrzeit eingeben"
}
})Input: Zeitdauer
Beschreibung
Wir möchten ein Input-Feld erstellen, mit dem wir ein Ninox-Zeitdauer-Feld beschreiben können.
Dafür legen wir als inputType den Wert "duration" fest und stellen unsere restlichen Konfigurationen wie gewohnt ein. Den value von fieldContent müssen wir dabei als raw(Zeitdauer) übergeben.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Duration" + Nr,
embedded: false,
contentEditable: true,
inputType: "duration",
style: "",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Zeitdauer"),
label: {
style: "color: orange",
value: "Zeitdauer",
orientation: "top"
},
fieldContent: {
value: raw(Zeitdauer)
},
placeholder: {
value: "Zeitdauer eingeben"
}
})))GIP_input({
uniqueId: "Duration" + Nr,
embedded: true,
contentEditable: true,
inputType: "duration",
style: "",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Zeitdauer"),
label: {
style: "color: orange",
value: "Zeitdauer",
orientation: "top"
},
fieldContent: {
value: raw(Zeitdauer)
},
placeholder: {
value: "Zeitdauer eingeben"
}
})Input: Termin
Beschreibung
Wir möchten ein Input-Feld erstellen, mit dem wir ein Ninox-Termin-Feld beschreiben können.
Dafür legen wir als inputType den Wert "appointment" fest und stellen unsere restlichen Konfigurationen wie gewohnt ein. Den value von fieldContent müssen wir dabei als raw(Termin) übergeben.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_input({
uniqueId: "Termin" + Nr,
embedded: false,
contentEditable: true,
inputType: "appointment",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Termin"),
label: {
style: "color: orange",
value: "Termin",
orientation: "top"
},
fieldContent: {
value: raw(Termin)
},
placeholder: {
value: "Termin eingeben"
}
})))GIP_input({
uniqueId: "Termin" + Nr,
embedded: true,
contentEditable: true,
inputType: "appointment",
formId: "",
recordId: raw(Nr),
fieldId: fieldId(this, "Termin"),
label: {
style: "color: orange",
value: "Termin",
orientation: "top"
},
fieldContent: {
value: raw(Termin)
},
placeholder: {
value: "Termin eingeben"
}
})Interaction
Interaction: Button mit Update-Action
Beschreibung
Wir möchten einen Button erstellen, der ein Ninox-Textfeld mit einem Text updated. Dafür müssen wir lediglich die ID des Ziel-Records, die ID des Ziel-Feldes und den Value angeben, der geschrieben werden soll.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_interaction({
uniqueId: "Generate Text" + Nr,
embedded: false,
direction: "",
class: "",
style: "",
blocks: [{
class: "",
style: "width: 100%;",
value: "Text generieren",
actions: [{
trigger: "click",
scripts: [{
type: "update",
recordId: raw(Nr),
fieldId: fieldId(this, "Text"),
value: "Hallo Welt"
}]
}]
}]
})))GIP_interaction({
uniqueId: "Generate Text" + Nr,
embedded: true,
direction: "",
class: "",
style: "",
blocks: [{
class: "",
style: "width: 100%;",
value: "Text generieren",
actions: [{
trigger: "click",
scripts: [{
type: "update",
recordId: raw(Nr),
fieldId: fieldId(this, "Text"),
value: "Hallo Welt"
}]
}]
}]
})Interaction: Button mit Create-Action
Beschreibung
Wir möchten einen Button erstellen, der einen neuen Record in unserer Tabelle erzeugt. Unseren aktuellen Record möchten wir mit diesem neu erstellten Record verknüpfen. Außerdem wollen wir im neuen Record einen Text in ein Textfeld schreiben. Nach dem erstellen soll der Record als Ninox-Popup geöffnet werden.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_interaction({
uniqueId: "Create Record" + Nr,
embedded: false,
direction: "",
class: "GIPColorRed",
style: "",
blocks: [{
style: "width: 100%;",
value: "Neuen Record erstellen und verknüpfen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "create",
tableId: "V",
tab: "",
changeFieldValues: [{
fieldId: fieldId(this, "Text"),
value: "Hallo neuer Record"
}],
displayAfterCreate: "popup",
setNewRecordId: [{
fieldId: fieldId(this, "Actions und Functions: Verknüpfter Record"),
recordId: Nr
}]
}]
}]
})))GIP_interaction({
uniqueId: "Create Record" + Nr,
embedded: true,
direction: "",
class: "GIPColorRed",
style: "",
blocks: [{
style: "width: 100%;",
value: "Neuen Record erstellen und verknüpfen"
}],
actions: [{
trigger: "click",
scripts: [{
type: "create",
tableId: "V",
tab: "",
changeFieldValues: [{
fieldId: fieldId(this, "Text"),
value: "Hallo neuer Record"
}],
displayAfterCreate: "popup",
setNewRecordId: [{
fieldId: fieldId(this, "Actions und Functions: Verknüpfter Record"),
recordId: Nr
}]
}]
}]
})Interaction: Global CSS-Classes

Beschreibung
Wir möchten ein GIP-Interaction stylen und dafür eine globale CSS-Class nutzen. Dafür können wir entweder eine Auswahl an GIP-Color-Classes nutzen (teilweise basierend auf Ninox-eigenen Button-Stylings) oder wir legen eine eigene CSS-Class an.
Infos zu den existierenden GIP-Color-Classes und dazu, wie du eigene CSS-Classes anlegst, findest du im Kapitel "Globaler CSS-Code".
Code des Beispiels
---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.MyCustomClass {
color: #FFAA3A;
border-width: 2px;
border-color: #7F0000;
border-style: dotted dashed solid double;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
html(raw(GIP_master({})) +
raw(GIP_layout({
uniqueId: "Horizontal" + Nr,
embedded: false,
direction: "horizontal",
style: "gap: 8px;",
blocks: [{
value: GIP_layout({
uniqueId: "Vertical1" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_interaction({
uniqueId: "GIPColorPlain" + Nr,
embedded: true,
class: "GIPColorPlain",
blocks: [{
value: "GIPColorPlain"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorPurple" + Nr,
embedded: true,
class: "GIPColorPurple",
blocks: [{
value: "GIPColorPurple"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorBlue" + Nr,
embedded: true,
class: "GIPColorBlue",
blocks: [{
value: "GIPColorBlue"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorRed" + Nr,
embedded: true,
class: "GIPColorRed",
blocks: [{
value: "GIPColorRed"
}]
})
}]
})
}, {
value: GIP_layout({
uniqueId: "Vertical2" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_interaction({
uniqueId: "GIPColorGreen" + Nr,
embedded: true,
class: "GIPColorGreen",
blocks: [{
value: "GIPColorGreen"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorWhite" + Nr,
embedded: true,
class: "GIPColorWhite",
blocks: [{
value: "GIPColorWhite"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorNyan" + Nr,
embedded: true,
class: "GIPColorNyan",
blocks: [{
value: "GIPColorNyan"
}]
})
}, {
value: GIP_interaction({
uniqueId: "MyCustomClass" + Nr,
embedded: true,
class: "MyCustomClass",
blocks: [{
value: "MyCustomClass"
}]
})
}]
})
}]
})))---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.MyCustomClass {
color: #FFAA3A;
border-width: 2px;
border-color: #7F0000;
border-style: dotted dashed solid double;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
GIP_layout({
uniqueId: "Horizontal" + Nr,
embedded: true,
direction: "horizontal",
style: "gap: 8px;",
blocks: [{
value: GIP_layout({
uniqueId: "Vertical1" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_interaction({
uniqueId: "GIPColorPlain" + Nr,
embedded: true,
class: "GIPColorPlain",
blocks: [{
value: "GIPColorPlain"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorPurple" + Nr,
embedded: true,
class: "GIPColorPurple",
blocks: [{
value: "GIPColorPurple"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorBlue" + Nr,
embedded: true,
class: "GIPColorBlue",
blocks: [{
value: "GIPColorBlue"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorRed" + Nr,
embedded: true,
class: "GIPColorRed",
blocks: [{
value: "GIPColorRed"
}]
})
}]
})
}, {
value: GIP_layout({
uniqueId: "Vertical2" + Nr,
embedded: true,
direction: "vertical",
style: "gap: 8px;",
blocks: [{
value: GIP_interaction({
uniqueId: "GIPColorGreen" + Nr,
embedded: true,
class: "GIPColorGreen",
blocks: [{
value: "GIPColorGreen"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorWhite" + Nr,
embedded: true,
class: "GIPColorWhite",
blocks: [{
value: "GIPColorWhite"
}]
})
}, {
value: GIP_interaction({
uniqueId: "GIPColorNyan" + Nr,
embedded: true,
class: "GIPColorNyan",
blocks: [{
value: "GIPColorNyan"
}]
})
}, {
value: GIP_interaction({
uniqueId: "MyCustomClass" + Nr,
embedded: true,
class: "MyCustomClass",
blocks: [{
value: "MyCustomClass"
}]
})
}]
})
}]
})Kanban
Kanban: Basic ohne Gruppen
Beschreibung
Wir möchten ein Kanban zur Verwaltung von Aufgaben bauen. Dabei sollen die Spalten des Kanbans jeweils einen Aufgaben-Status darstellen.
Im Key kanbanColumns erstellen wir zunächst pro Projektstatus ein Object, indem wir durch die Stati iterieren. Für jede dieser Status-Spalten suchen wir uns dann die dazugehörigen Aufgaben, welche wir als cards übergeben.
{
uniqueId: "ProjektAufgabenVerwaltungBasic" + Nr,
embedded: false,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
let columnTasks := tasks[number(Status) = number(column)];
column.{
class: "",
style: "",
cards: for card in columnTasks do
card.{
class: "",
style: "border-left: 6px solid " + Verantwortlicher.Farbe + ";",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
}Nachdem die Aufgaben in Spalten eingeordnet sind, legen wir noch fest, welchen Titel unsere Spalten haben sollen und ob die Spalten eingeklappt werden können. Wir können mit collapseChildren außerdem einen initialen Einklappstatus festlegen.
{
uniqueId: "ProjektAufgabenVerwaltungBasic" + Nr,
embedded: false,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
let columnTasks := tasks[number(Status) = number(column)];
column.{
class: "",
style: "",
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cards: for card in columnTasks do
card.{
class: "",
style: "border-left: 6px solid " + Verantwortlicher.Farbe + ";",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
}Zuletzt müssen wir noch festlegen, welche Ninox-Felder beim Verschieben einer Aufgabe in eine andere Spalte passieren soll. In unserem Fall möchten wir das Statusfeld in der Aufgabe aktualisieren. Dafür übergeben in dropUpdates in einem Object die Field-ID des Status-Feldes in den Aufgaben und der neue Wert, der gesetzt werden soll, in diesem Fall die Number des Status der Spalte.
{
uniqueId: "ProjektAufgabenVerwaltungBasic" + Nr,
embedded: false,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
let columnTasks := tasks[number(Status) = number(column)];
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cards: for card in columnTasks do
card.{
class: "",
style: "border-left: 6px solid " + Verantwortlicher.Farbe + ";",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
}Es könnten auch noch weitere dropUpdates definiert werden, z.B. welcher Nutzer die Aufgabe zuletzt verschoben hat.
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
},{
fieldId: fieldId(first(tasks), "Nutzer"),
value: user()
}],Code des Beispiels
let allStati := ((select Status) order by Reihenfolge);
let tasks := (select Aufgaben);
html(raw(GIP_master({})) +
raw(GIP_kanban({
uniqueId: "ProjektAufgabenVerwaltungBasic" + Nr,
embedded: false,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
let columnTasks := tasks[number(Status) = number(column)];
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cards: for card in columnTasks do
card.{
class: "",
style: "border-left: 6px solid " + Verantwortlicher.Farbe + ";",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
})))let allStati := ((select Status) order by Reihenfolge);
let tasks := (select Aufgaben);
GIP_kanban({
uniqueId: "ProjektAufgabenVerwaltungBasic" + Nr,
embedded: true,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
let columnTasks := tasks[number(Status) = number(column)];
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cards: for card in columnTasks do
card.{
class: "",
style: "border-left: 6px solid " + Verantwortlicher.Farbe + ";",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
})Kanban: Mit Gruppen
Beschreibung
Wir möchten ein Kanban anlegen, in dem unsere Spalten verschiedene Aufgaben-Stati sind. Zusätzlich möchten wir innerhalb dieser Spalten die Aufgaben nach Verantwortlichen gruppieren.
Zunächst legen wir wie gewohnt unsere kanbanColumns an. In diesen definieren wir das dropUpdate für die Spalte: Es soll das Feld "Status" mit dem Status der Spalte aktualisiert werden.
{
uniqueId: "ProjektAufgabenVerwaltungGroups" + Nr,
embedded: true,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
}
}
end
}Nun legen wir noch Gruppen für die Verantwortlichen in jeder Spalte an. Dafür definieren wir cardGroups innerhalb der kanbanColumns. Die Struktur der Gruppen und der Spalten ist identisch, wir ersetzen nur die Werte der Keys. Bei dropUpdates der cardGroups beziehen wir uns in auf der Feld "Verantwortlicher" in unseren Aufgaben und übergeben die ID des Verantwortlichen. Die cards, also die Aufgaben, übergeben wir in den cardGroups.
{
uniqueId: "ProjektAufgabenVerwaltungGroups" + Nr,
embedded: true,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cardGroups: for teamMember in teamMembers do
let groupTasks := tasks[number(Status) = number(column) and number(Verantwortlicher) = number(teamMember)];
teamMember.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Verantwortlicher"),
value: number(this)
}],
collapsible: true,
collapseChildren: false,
titleContent: {
class: "",
style: "color: " + Farbe + ";",
value: Name
},
cards: for card in groupTasks do
card.{...}
end
}
end
}
end
}Die definierten dropUpdates der Spalten und Gruppen funktionieren sowohl separat (eine Aufgabe in eine neue Spalte ODER eine neue Gruppe ziehen), als auch zusammen (eine Aufgabe in eine neue Spalte UND eine neue Gruppe ziehen). Das bedeutet, dass man der Aufgabe gleichzeitig einen neuen Status und einen neuen Verantwortlichen zuweisen kann.
Code des Beispiels
let allStati := ((select Status) order by Reihenfolge);
let teamMembers := (select Mitarbeiter);
let tasks := (select Aufgaben);
html(raw(GIP_master({})) +
raw(GIP_kanban({
uniqueId: "ProjektAufgabenVerwaltungGroups" + Nr,
embedded: false,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cardGroups: for teamMember in teamMembers do
let groupTasks := tasks[number(Status) = number(column) and number(Verantwortlicher) = number(teamMember)];
teamMember.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Verantwortlicher"),
value: number(this)
}],
collapsible: true,
collapseChildren: false,
titleContent: {
class: "",
style: "color: " + Farbe + ";",
value: Name
},
cards: for card in groupTasks do
card.{
class: "",
style: "",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
}
end
})))let allStati := ((select Status) order by Reihenfolge);
let teamMembers := (select Mitarbeiter);
let tasks := (select Aufgaben);
GIP_kanban({
uniqueId: "ProjektAufgabenVerwaltungGroups" + Nr,
embedded: true,
class: "",
style: "height: 600px;",
kanbanColumns: for column in allStati do
column.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Status"),
value: number(this)
}],
collapsible: true,
collapseChildren: {
recordId: raw(Nr),
fieldId: fieldId(this, "Collapse in Kanban"),
value: 'Collapse in Kanban'
},
titleContent: {
class: "",
style: "background-color: " + Farbe,
value: Bezeichnung
},
cardGroups: for teamMember in teamMembers do
let groupTasks := tasks[number(Status) = number(column) and number(Verantwortlicher) = number(teamMember)];
teamMember.{
class: "",
style: "",
dropUpdates: [{
fieldId: fieldId(first(tasks), "Verantwortlicher"),
value: number(this)
}],
collapsible: true,
collapseChildren: false,
titleContent: {
class: "",
style: "color: " + Farbe + ";",
value: Name
},
cards: for card in groupTasks do
card.{
class: "",
style: "",
recordId: raw(Nr),
draggable: true,
value: Bezeichnung,
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: raw(Nr)
}]
}]
}
end
}
end
}
end
})Layout
Layout: Text anordnen

Beschreibung
Wir möchten Inhalt mit dem Layout-Modul anordnen, in diesem Beispiel den Text für ein Brot-Rezept.
Um die Überschrift "Rezept für Dinkel-Mischbrot" oberhalb des eigentlichen Rezepts anzulegen, benötigen wir zuerst ein vertikales Layout mit zwei Blöcken.Der erste Block enthält die Überschrift, der zweite Block ist für das Rezept.
GIP_layout({
uniqueId: "Outer Layout" + Nr,
embedded: false,
direction: "vertical",
blocks: [{
style: "",
value: "Rezept für Dinkel-Mischbrot"
},
{
style: "",
value: "" //Hier kommt gleich der Inhalt für das Rezept rein.
}]
})Dem Block der Überschrift geben wir einen Inline-Style, um die Aspekte wie Schriftart, Farbe, Größe, etc.einzustellen und den Text mittig im Block darzustellen.
color: #7F0000; font: small-caps bold 25px/2 times-new-roman; text-align: center;Das Rezept selbst ordnen wir mit einem weiteren Layout in zwei Spalten an, um links unsere Mengenangaben und rechts die Anweisungen anzuzeigen.Das Layout hat in diesem Fall die Ausrichtung "horizontal" und istembedded: true.
GIP_layout({
uniqueId: "Outer Layout" + Nr,
embedded: false,
direction: "vertical",
blocks: [{
style: "color: #7F0000; font: small-caps bold 25px/2 times-new-roman; text-align: center;",
value: "Rezept für Dinkel-Mischbrot"
},
{
style: "",
value: GIP_layout({
uniqueId: "Inner Layout" + Nr,
embedded: true,
direction: "horizontal",
blocks: [{
style: "",
value: "" //Hier kommen gleich die Mengenangaben rein.
},
{
style: "",
value: "" //Hier kommen gleich die Rezeptschritte rein.
}]
})
}]
})Für dieses zweite Layout verändern wir nun insgesamt Schriftart, Größe, Zeilenabstand und Farbe:
color: #1F305E; font: 14px/2 arial;Zusätzlich zu diesem Styling erhalten die beiden Layout-Blöcke noch eine Breite, Padding und im Fall des linken Blocks eine Border.Die Texte schreiben wir jeweils als HTML-Listen.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_layout({
uniqueId: "Outer Layout" + Nr,
embedded: false,
direction: "vertical",
blocks: [{
style: "color: #7F0000; font: small-caps bold 25px/2 times-new-roman; text-align: center; display: inline-block;",
value: "Rezept für Dinkel-Mischbrot"
},
{
style: "color: #1F305E; font: 14px/2 arial;",
value: GIP_layout({
uniqueId: "Inner Layout" + Nr,
embedded: true,
direction: "horizontal",
blocks: [{
style: "width: 400px; padding: 15px; align-items: stretch; border-right: 1px dashed;",
value: "<ul>
<li>7 g Hefe</li>
<li>20 g Salz</li>
<li>45 g Rapsöl</li>
<li>650 g Wasser</li>
<li>500 g Dinkelmehl, Type 1050</li>
<li>500 g Dinkelmehl, Type 630</li>
</ul>"
},
{
style: "width: 100%; padding: 15px; align-items: stretch;",
value: "<ol>
<li>Hefe, Salz, Rapsöl und Wasser in einer großen Schüssel mit einem Schneebesen vermischen.</li>
<li>Dinkelmehl, Type 1050, in die Flüssigkeit mit einmischen</li>
<li>Dinkelmehl, Type 630, nach uns nach einmischen. Wenn der Teig zu fest für den Schneebesen wird, entweder das Mehl per Hand und einer Teigkarte weiter einarbeiten oder eine Küchenmaschine mit Knethaken verwenden.</li>
<li>Teig eine halbe Stunde **bei Raumtemperatur** gehen lassen. Danach den Teig zusammenfalten, um Spannung aufzubauen.</li>
<li>Nach dem ersten Falten den Teig **im Kühlschrank** gehen lassen. Über 2 Stunden verteilt mehrmals zusammenfalten (etwa alle halbe Stunde).</li>
<li>Teig über Nacht im Kühlschrank gehen lassen (zwischen 12 und 24 Stunden).</li>
<li>Am Backtag den Teig eine halbe Stunde bis eine Stunde vor dem Backen aus dem Kühlschrank nehmen und anwärmen lassen.</li>
<li>Teig in gewünschter Weise formen und gehen lassen. Backofen auf 200°C Ober-/Unterhitze anheizen.</li>
<li>Teigling für dem Backen einschneiden und mit Wasser besprühen. Danach in den Ofen schieben und 5-10 Minuten anbacken.</li>
<li>Temperatur auf 190°C reduzieren und fertig backen (etwa weitere 40 Minuten). Das Brot ist durch, wenn die Innentemperatur 95°C beträgt, bzw. es sich hohl anhört, wenn man auf den Boden klopft.</li>
<li>Nach dem Backen auf einem Gitter auskühlen lassen.</li>
</ol>"
}]
})
}]
})
))GIP_layout({
uniqueId: "Outer Layout" + Nr,
embedded: true,
direction: "vertical",
blocks: [{
style: "color: #7F0000; font: small-caps bold 25px/2 times-new-roman; text-align: center; display: inline-block;",
value: "Rezept für Dinkel-Mischbrot"
},
{
style: "color: #1F305E; font: 14px/2 arial;",
value: GIP_layout({
uniqueId: "Inner Layout" + Nr,
embedded: true,
direction: "horizontal",
blocks: [{
style: "width: 400px; padding: 15px; align-items: stretch; border-right: 1px dashed;",
value: "<ul>
<li>7 g Hefe</li>
<li>20 g Salz</li>
<li>45 g Rapsöl</li>
<li>650 g Wasser</li>
<li>500 g Dinkelmehl, Type 1050</li>
<li>500 g Dinkelmehl, Type 630</li>
</ul>"
},
{
style: "width: 100%; padding: 15px; align-items: stretch;",
value: "<ol>
<li>Hefe, Salz, Rapsöl und Wasser in einer großen Schüssel mit einem Schneebesen vermischen.</li>
<li>Dinkelmehl, Type 1050, in die Flüssigkeit mit einmischen</li>
<li>Dinkelmehl, Type 630, nach uns nach einmischen. Wenn der Teig zu fest für den Schneebesen wird, entweder das Mehl per Hand und einer Teigkarte weiter einarbeiten oder eine Küchenmaschine mit Knethaken verwenden.</li>
<li>Teig eine halbe Stunde **bei Raumtemperatur** gehen lassen. Danach den Teig zusammenfalten, um Spannung aufzubauen.</li>
<li>Nach dem ersten Falten den Teig **im Kühlschrank** gehen lassen. Über 2 Stunden verteilt mehrmals zusammenfalten (etwa alle halbe Stunde).</li>
<li>Teig über Nacht im Kühlschrank gehen lassen (zwischen 12 und 24 Stunden).</li>
<li>Am Backtag den Teig eine halbe Stunde bis eine Stunde vor dem Backen aus dem Kühlschrank nehmen und anwärmen lassen.</li>
<li>Teig in gewünschter Weise formen und gehen lassen. Backofen auf 200°C Ober-/Unterhitze anheizen.</li>
<li>Teigling für dem Backen einschneiden und mit Wasser besprühen. Danach in den Ofen schieben und 5-10 Minuten anbacken.</li>
<li>Temperatur auf 190°C reduzieren und fertig backen (etwa weitere 40 Minuten). Das Brot ist durch, wenn die Innentemperatur 95°C beträgt, bzw. es sich hohl anhört, wenn man auf den Boden klopft.</li>
<li>Nach dem Backen auf einem Gitter auskühlen lassen.</li>
</ol>"
}]
})
}]
})Material Symbols
Material Symbol: Basic

Beschreibung
Wir möchten ein einfaches Material Symbol ohne Füllung oder Zweifarbigkeit erstellen.
Zunächst suchen wir uns den Namen des Material Symbols auf der Google Fonts Website heraus. Danach setzen wir diesen und die Farbe, in der wir das Symbol darstellen wollen, in den Modulcode ein.
GIP_materialSymbols({
embedded: false,
color: "#00369d",
icon: "cloud_done" //Icon Name das Material Symbols.
})Zusätzlich möchten wir die Größe des Symbols erhöhen. Die Standardgröße von 1.25 rem, in der auch Ninox-Symbolfelder die Symbole darstellen, ist uns hier gerade zu gering. Wir möchten das Symbol um das 10-fache vergrößern und vergeben daher einen Scaling Factor von 10:
GIP_materialSymbols({
embedded: false,
scalingFactor: 10, //Vergrößert das Material Symbol um den angegebenen Faktor.
color: "#00369d",
icon: "cloud_done"
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_materialSymbols({
embedded: false,
scalingFactor: 10,
filling: false,
color: "#00369d",
icon: "cloud_done"
})
))GIP_materialSymbols({
embedded: true,
scalingFactor: 10,
filling: false,
color: "#00369d",
icon: "cloud_done"
})Material Symbol: Gefüllt

Beschreibung
Wir möchten ein Material Symbol mit Füllung, aber ohne Zweifarbigkeit erstellen.
Zunächst suchen wir uns den Namen des Material Symbols auf der Google Fonts Website heraus. Danach setzen wir diesen und die Farbe, in der wir das Symbol darstellen wollen, in den Modulcode ein. Um das Symbol gefüllt anzuzeigen, setzen wir filling: true oder filling: 1.
GIP_materialSymbols({
embedded: false,
filling: true, //true oder 1: Das Symbol wird gefüllt dargestellt. false oder 0: Das Symbol wird ohne Füllung dargestellt.
color: "#00369d",
icon: "cloud_done" //Icon Name das Material Symbols.
})Zusätzlich möchten wir die Größe des Symbols erhöhen. Die Standardgröße von 1.25 rem, in der auch Ninox-Symbolfelder die Symbole darstellen, ist uns hier gerade zu gering. Wir möchten das Symbol um das 10-fache vergrößern und vergeben daher einen Scaling Factor von 10:
GIP_materialSymbols({
embedded: false,
scalingFactor: 10, //Vergrößert das Material Symbol um den angegebenen Faktor.
filling: true,
color: "#00369d",
icon: "cloud_done"
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_materialSymbols({
embedded: false,
scalingFactor: 10,
filling: true,
color: "#00369d",
icon: "cloud_done"
})
))GIP_materialSymbols({
embedded: true,
scalingFactor: 10,
filling: true,
color: "#00369d",
icon: "cloud_done"
})Material Symbol: Zweifarbig

Beschreibung
Wir möchten ein zweifarbiges Material Symbol erstellen.
Zunächst suchen wir uns den Namen des Material Symbols auf der Google Fonts Website heraus. Danach setzen wir diesen und die zwei Farben, in denen wir das Material Symbol darstellen wollen, in den Modulcode ein. Dabei bestimmt der color-Key die Rahmenfarbe und der secondColor-Key die Hintergrundfarbe.
GIP_materialSymbols({
embedded: false,
color: "#00369d",
secondColor: "#ccd4ff",
icon: "cloud_done" //Icon Name das Material Symbols.
})Zusätzlich möchten wir die Größe des Symbols erhöhen. Die Standardgröße von 1.25 rem, in der auch Ninox-Symbolfelder die Symbole darstellen, ist uns hier gerade zu gering. Wir möchten das Symbol um das 10-fache vergrößern und vergeben daher einen Scaling Factor von 10:
GIP_materialSymbols({
embedded: false,
scalingFactor: 10, //Vergrößert das Material Symbol um den angegebenen Faktor.
color: "#00369d",
secondColor: "#ccd4ff",
icon: "cloud_done"
})Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_materialSymbols({
embedded: false,
scalingFactor: 10,
color: "#00369d",
secondColor: "#ccd4ff",
icon: "cloud_done"
})
))GIP_materialSymbols({
embedded: true,
scalingFactor: 10,
color: "#00369d",
secondColor: "#ccd4ff",
icon: "cloud_done"
})Select
Select: Einfachauswahl

Beschreibung
Wir möchten eine Einfachauswahl im Combobox-Stil bauen, die ein Ninox-Auswahlfeld "Antwortoptionen" updated. Dafür vergeben wir "single" als selectType und konfigurieren unsere Combobox.
Im Key items übergeben wir die Auswahloptionen für das Select. Für die itemId wählen wir hier dieselbe ID, die auch im Ninox-Auswahlfeld vergeben ist. 
Um dem Nutzer zusätzlich die Option zu geben, die Auswahl wieder zu leeren übergeben wir für den Key toggleButtonNone den Wert "(leer)".
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "SingleBasic" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
recordId: raw(Nr),
fieldId: fieldId(this, "Antwortoptionen"),
label: {
class: "",
style: "",
value: "Single Select (basic)"
},
combobox: {
class: "",
style: "",
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Antwort wählen..."
}
},
toggleButtonNone: "(leer)",
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: number(Antwortoptionen),
items: [{
itemId: 1,
style: "",
value: "Ja"
}, {
itemId: 2,
style: "",
value: "Nein"
}, {
itemId: 3,
style: "",
value: "Vielleicht"
}]
})))GIP_select({
uniqueId: "SingleBasic" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
recordId: raw(Nr),
fieldId: fieldId(this, "Antwortoptionen"),
label: {
class: "",
style: "",
value: "Single Select (basic)"
},
combobox: {
class: "",
style: "",
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Antwort wählen..."
}
},
toggleButtonNone: "(leer)",
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: number(Antwortoptionen),
items: [{
itemId: 1,
style: "",
value: "Ja"
}, {
itemId: 2,
style: "",
value: "Nein"
}, {
itemId: 3,
style: "",
value: "Vielleicht"
}]
})Select: Mehrfachauswahl

Beschreibung
Wir möchten eine Mehrfachauswahl im Combobox-Stil bauen, die ein Ninox-Auswahlfeld "Einkaufen" updated. Dafür vergeben wir "multi" als selectType an und konfigurieren unsere Combobox. Mit dem Type "multi" brauchen wir keinerlei Hilfsfelder, um das Ninox-Mehrfachauswahl-Feld zu updaten.
Im Key items übergeben wir die Auswahloptionen für das Select. Für die itemId wählen wir hier dieselbe ID, die auch im Ninox-Auswahlfeld vergeben ist, in diesem Fall eine Zahl: 
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "MultiBasic" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Einkaufsliste schreiben..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Einkaufen"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (basic)"
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers(Einkaufen),
items: [{
itemId: 1,
style: "",
value: "Apfel"
}, {
itemId: 2,
style: "",
value: "Mehl"
}, {
itemId: 3,
style: "",
value: "Butter"
}, {
itemId: 4,
style: "",
value: "KiBa"
}]
})))GIP_select({
uniqueId: "MultiBasic" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Einkaufsliste schreiben..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Einkaufen"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (basic)"
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers(Einkaufen),
items: [{
itemId: 1,
style: "",
value: "Apfel"
}, {
itemId: 2,
style: "",
value: "Mehl"
}, {
itemId: 3,
style: "",
value: "Butter"
}, {
itemId: 4,
style: "",
value: "KiBa"
}]
})Select: Einfachauswahl mit Custom Icons
![]()
Beschreibung
Wir möchten ein Select-Modul bauen und dabei die Checkboxen durch eigene Symbole ersetzen, hier beispielhaft für eine Einfachauswahl. Dafür übergeben wir in den Keys iconSelected und iconUnselected Material-Symbols, die wir wiederum stylen können.
Code des Beispiels
let workers := (select Mitarbeiter);
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "SingleCustomIcons" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortlicher Mitarbeiter (single)"),
label: {
class: "",
style: "",
value: "Single Select (Custom Icons)"
},
iconSelected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_checked"
}),
iconUnselected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_unchecked"
}),
selectOnAll: true,
selectedItems: number('Verantwortlicher Mitarbeiter (single)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})))let workers := (select Mitarbeiter);
GIP_select({
uniqueId: "SingleCustomIcons" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortlicher Mitarbeiter (single)"),
label: {
class: "",
style: "",
value: "Single Select (Custom Icons)"
},
iconSelected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_checked"
}),
iconUnselected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_unchecked"
}),
selectOnAll: true,
selectedItems: number('Verantwortlicher Mitarbeiter (single)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})Select: Einfachauswahl mit Searchbar

Beschreibung
Wir möchten ein Select-Modul mit einer Suchleiste bauen, hier beispielhaft mit einer Einfachauswahl. Dafür können wir entweder true für den Key searchBar übergeben, oder wie im Beispiel-Code gezeigt ein Object mit weiteren Einstellungen zur Suchleiste, wie den Platzhalter.
Code des Beispiels
let workers := (select Mitarbeiter);
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "SingleSearchbar" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortlicher Mitarbeiter (single)"),
label: {
class: "",
style: "",
value: "Single Select (Searchbar)"
},
searchBar: {
style: "",
placeholder: {
style: "",
value: "Suchen..."
}
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: number('Verantwortlicher Mitarbeiter (single)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})))let workers := (select Mitarbeiter);
GIP_select({
uniqueId: "SingleSearchbar" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "single",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: true,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortlicher Mitarbeiter (single)"),
label: {
class: "",
style: "",
value: "Single Select (Searchbar)"
},
searchBar: {
style: "",
placeholder: {
style: "",
value: "Suchen..."
}
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: number('Verantwortlicher Mitarbeiter (single)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})Select: Mehrfachauswahl mit Toggle-Button

Beschreibung
Wir möchten eine Mehrfachauswahl bauen, in der wir Button haben, um alle Optionen an- bzw. abzuwählen. Dafür nutzen wir die Keys toggleButtonAll und toggleButtonNone. In diesem Beispiel setzen wir die Werte beider Keys auf true, um sie mit Default Einstellungen anzuzeigen. Wir können aber auch einen String oder ein Modul übergeben, um den Text und die Erscheinung der Button zu personalisieren.
Code des Beispiels
let workers := (select Mitarbeiter);
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "MultiToggleButton" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Toggle Button)"
},
toggleButtonNone: true,
toggleButtonAll: true,
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})))let workers := (select Mitarbeiter);
GIP_select({
uniqueId: "MultiToggleButton" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Toggle Button)"
},
toggleButtonNone: true,
toggleButtonAll: true,
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})Select: Mehrfachauswahl ohne Combobox

Beschreibung
Wir möchten ein Select-Modul ohne Combobox bauen, hier beispielhaft für eine Mehrfachauswahl. Dafür können wir für den Key combobox den Wert false übergeben oder, wie im Beispiel-Code, den Key komplett weg lassen.
Code des Beispiels
let workers := (select Mitarbeiter);
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "MultiOhneCombobox" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Ohne Combobox)"
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})))let workers := (select Mitarbeiter);
GIP_select({
uniqueId: "MultiOhneCombobox" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Ohne Combobox)"
},
iconSelected: true,
iconUnselected: true,
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})Select: Mehrfachauswahl Fortgeschritten

Beschreibung
Wir möchten ein Select-Modul bauen, das viele der möglichen Optionen vereint: Combobox, Searchbar, Toggle-Button und selbst definierte Symbole. Dafür vergeben wir in den entsprechenden Keys entweder den Wert true oder weitere Eigenschaften als Object oder String.
Code des Beispiels
let workers := (select Mitarbeiter);
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "MultiAdvanced" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
searchBar: {
style: "",
placeholder: {
style: "",
value: "Suchen..."
}
},
toggleButtonNone: true,
toggleButtonAll: true,
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Advanced)"
},
iconSelected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_checked"
}),
iconUnselected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_unchecked"
}),
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})))let workers := (select Mitarbeiter);
GIP_select({
uniqueId: "MultiAdvanced" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: {
class: "",
style: "",
expandIcon: true,
expandOnAll: true,
collapseAfterSelect: false,
placeholder: {
style: "",
value: "Mitarbeiter wählen..."
}
},
searchBar: {
style: "",
placeholder: {
style: "",
value: "Suchen..."
}
},
toggleButtonNone: true,
toggleButtonAll: true,
recordId: raw(Nr),
fieldId: fieldId(this, "Verantwortliche Mitarbeiter (multi)"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Advanced)"
},
iconSelected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_checked"
}),
iconUnselected: GIP_materialSymbols({
embedded: true,
color: "#3381ff",
icon: "radio_button_unchecked"
}),
selectOnAll: true,
selectedItems: numbers('Verantwortliche Mitarbeiter (multi)'),
items: workers.{
style: "",
value: Name,
itemId: number(Nr)
}
})Select: Mehrfachauswahl Fortgeschritten

Beschreibung
Wir möchten ein Select-Modul in Switch-Darstellung bauen, hier am Beispiel einer Mehrfachauswahl. Dieser Switch soll keine Checkboxen in den einzelnen Items haben und ausgewählte Items sollen mit blauem Hintergrund dargestellt werden.
Zunächst müssen wir die Combobox deaktivieren, um die Items direkt angezeigt zu bekommen. Nun möchten wir diese Items aber nicht untereinander, sondern nebeneinander darstellen. Außerdem soll der Text innerhalb der Items zentriert sein. Dafür geben wir itemGroups den style "display: flex; flex-direction: row; text-align: center;".
Das Styling der ausgewählten Items bestimmen wir mit dem Key styleSelected. Optional können wir auch den Style beim Überfahren mit der Maus anpassen über styleHovered. Zuletzt geben wir noch allen Items, außer dem letzten, eine Rahmenlinie rechts, um die Items optisch voneinander zu trennen.
Code des Beispiels
html(raw(GIP_master({})) +
raw(GIP_select({
uniqueId: "MultiSwitch" + Nr,
embedded: false,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: false,
recordId: raw(Nr),
fieldId: fieldId(this, "Einkaufen"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Switch)"
},
selectContainer: {
class: "",
style: "",
itemGroup: {
class: "",
style: "display: flex; flex-direction: row; text-align: center;",
styleSelected: "background-color: #3381ff; color: white;",
styleHovered: "background-color: #f1f1f4;",
iconSelected: false,
iconUnselected: false,
selectOnAll: true,
selectedItems: numbers(Einkaufen),
items: [{
itemId: 1,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Apfel"
}, {
itemId: 2,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Mehl"
}, {
itemId: 3,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Butter"
}, {
itemId: 4,
style: "",
value: "KiBa"
}]
}
}
})))GIP_select({
uniqueId: "MultiSwitch" + Nr,
embedded: true,
class: "",
style: "max-height: 400px; height:auto;",
selectType: "multi",
combobox: false,
recordId: raw(Nr),
fieldId: fieldId(this, "Einkaufen"),
formId: "",
htmlAttribute: "",
label: {
class: "",
style: "",
value: "Multi Select (Switch)"
},
selectContainer: {
class: "",
style: "",
itemGroup: {
class: "",
style: "display: flex; flex-direction: row; text-align: center;",
styleSelected: "background-color: #3381ff; color: white;",
styleHovered: "background-color: #f1f1f4;",
iconSelected: false,
iconUnselected: false,
selectOnAll: true,
selectedItems: numbers(Einkaufen),
items: [{
itemId: 1,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Apfel"
}, {
itemId: 2,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Mehl"
}, {
itemId: 3,
style: "border-right: 1px solid; border-color: #E9ECF4;",
value: "Butter"
}, {
itemId: 4,
style: "",
value: "KiBa"
}]
}
}
})Table
Table: Basic ohne Gruppen
Beschreibung
Wir möchten eine Table bauen, in der wir Projekt-Aufgaben anzeigen mit Informationen zum Kunden, Projekt, Verantwortlichen, Priorität und Status der Aufgabe. Zusätzlich möchten wir bei Hover über Kunden, Projekte und Aufgaben jeweils einen Button angezeigt bekommen, mit dem wir in den entsprechenden Record springen können.
Um alle Daten in unserer Tabelle anzeigen zu können, benötigen wir 6 Spalten. Wir beginnen damit, im header diese 6 Spalten als headerColumns anzulegen, ihnen jeweils einen Spaltentitel (value) und eine Breite (columnWidth) zu geben. Diese festgelegte Breite wird automatisch auf alle Zellen der Spalte übertragen, inkl. dem Footer.
headerColumns: [{
style: "",
columnWidth: "3fr", // Die Spaltenbreite kann in Einheiten wie Fraction (fr) oder Pixel (px) angegeben werden. Wenn "auto" angegeben wird, passt sich die Spalte auf den Inhalt des Headers an.
value: "Kunde"
}, {
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
}Nach der Definition des Headers füllen wir den Body mit Daten. Wir vergeben eine feste rowHeight, sodass alle Zeilen der Tabelle eine einheitliche Höhe haben. Es kann ein Platzhalter definiert werden, für den Fall, dass keine Zeilen in der Tabelle angezeigt werden (z.B. weil es noch keine Aufgaben gibt oder weil mit den aktiven Filtern keine Aufgaben gefunden wurden).
Um den nun die Zeilen der Tabelle zu übergeben, nutzen wir den Key rows. Hierin iterieren wir durch unsere Aufgaben (projectTasks), um eine Zeile pro Aufgabe zu erhalten. Pro Zeile legen wir im Key columns die Zellen (Spalten) der Zeile fest. Jede Zelle besitzt einen value und kann ihr eigenes Styling haben. Außerdem legen wir für ausgewählte Spalten ein hoverElement fest. Dies ist ein Button, der beim Überfahren der Zelle mit der Maus erscheint. Als Action legen wir fest, dass der jeweilige Record des Kunden, des Projektes oder der Aufgabe geöffnet werden soll.
Wichtig ist, dass wir in den columns genauso viele Spalten definieren, wie wir headerCoulmns definiert haben. Ansonsten kommt es zu falschen Anzeigen und Umbrüchen der Spalten.
rows: for task in projectTasks do
task.{
style: "",
columns: [{
style: "",
hoverElement: if Projekte.Kunde then
{
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Kunde.Nr
}]
}]
}
end,
value: Projekte.Kunde.Kundenname
}, {
style: "",
hoverElement: if Projekte then
{
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Nr
}]
}]
}
end,
value: Projekte.Projektname
}, {
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
endSchließlich können wir auch für den Footer noch footerColumns festlegen, z.B. um die Anzahl der abgeschlossenen Aufgaben anzugeben. Die Nutzung des Footers ist optional, aber wenn er verwendet wird, muss auch hier auf die richtige Anzahl der Spalten geachtet werden.
footerColumns: [{
style: "",
value: cnt(unique(projectTasks.Projekte.Kunde)) + " Kunden"
}, {
style: "",
value: cnt(unique(projectTasks.Projekte)) + " Projekte"
}, {
style: "",
value: cnt(projectTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectTasks.Verantwortlicher)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectTasks[number(Status) = 5]) + " Abgeschlossen"
}]Hinweis: Mit den richtigen CSS-Stylings können Zellen auch spaltenübergreifend zusammengefasst werden, z.B. um eine durchgehende Footer-Zeile zu erzeugen.
Code des Beispiels
let projectTasks := (select Aufgaben);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "OhneGruppierung" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "3fr",
value: "Kunde"
}, {
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for task in projectTasks do
task.{
style: "",
columns: [{
style: "",
hoverElement: if Projekte.Kunde then
{
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Kunde.Nr
}]
}]
}
end,
value: Projekte.Kunde.Kundenname
}, {
style: "",
hoverElement: if Projekte then
{
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Nr
}]
}]
}
end,
value: Projekte.Projektname
}, {
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(unique(projectTasks.Projekte.Kunde)) + " Kunden"
}, {
style: "",
value: cnt(unique(projectTasks.Projekte)) + " Projekte"
}, {
style: "",
value: cnt(projectTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectTasks.Verantwortlicher)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let projectTasks := (select Aufgaben);
GIP_table({
uniqueId: "OhneGruppierung" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "3fr",
value: "Kunde"
}, {
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for task in projectTasks do
task.{
style: "",
columns: [{
style: "",
hoverElement: if Projekte.Kunde then
{
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Kunde.Nr
}]
}]
}
end,
value: Projekte.Kunde.Kundenname
}, {
style: "",
hoverElement: if Projekte then
{
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Nr
}]
}]
}
end,
value: Projekte.Projektname
}, {
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(unique(projectTasks.Projekte.Kunde)) + " Kunden"
}, {
style: "",
value: cnt(unique(projectTasks.Projekte)) + " Projekte"
}, {
style: "",
value: cnt(projectTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectTasks.Verantwortlicher)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Eine Gruppenebene
Beschreibung
Wir möchten eine Table bauen, in der wir Projekt-Aufgaben anzeigen mit Informationen zum Kunden, Projekt, Verantwortlichen, Priorität und Status der Aufgabe. Für eine bessere Übersichtlichkeit möchten wir nach dem Kunden gruppieren.
Wie üblich beginnen wir damit, unseren header und die headerColumns zu definieren. Allerdings brauchen wir hier nur 5 Spalten, da wir unseren gruppierten Wert nicht in einer eigenen Spalte darstellen müssen.
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
}Um unsere Gruppierung zu erhalten, verwenden wir im body den Key groups. Als Array of Objects übergeben wir an dieser Stelle alle Gruppen, also alle Kunden. Für jede Gruppe können wir Einstellungen (z.B. style, class,...), Gruppenspalten (groupColumns) und untergeordnete Zeilen (rows) übergeben.
Die Definition der groupColumns ist ähnlich zu den normalen Columns: Wir übergeben eine Array ob Objects, wobei jedes Object eine Spalte ist. Für jede Spalte der Gruppenzeilen können wir Stylings, den anzuzeigenden Wert und Actions festlegen. Im Gegensatz zu den normalen Columns besitzt groupColumns noch den Key clickToCollapse. Wenn beispielsweise ein Button in einer Spalte enthalten ist, können wir mit clickToCollapse: false verhindern, dass die Gruppe bei jeden Klick auf den Button ein-/aufklappt.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: [{}]
}
}Für die komplette Gruppe legen wir mit dem Key collapsible fest, ob sie überhaupt ein-/ausklappbar sein soll. Zusätzlich können wir mit collapseChildren einstellen, ob die Gruppe beim ersten Laden der Table ausgeklappt sein soll (mit einem Object statt einem Boolean-Wert könnte hier auch auf ein Ninox 'Ja / Nein'-Feld verwiesen werden).
In rows übergeben wir nun diejenigen Aufgaben, die den Projekten des aktuellen Kunden zugeordnet sind. Pro Aufgabe bauen wir nun wie üblich unsere Row-Objects.
Wichtig ist, dass wir in den groupColumns und columns genauso viele Spalten definieren, wie wir headerCoulmns definiert haben. Ansonsten kommt es zu falschen Anzeigen und Umbrüchen der Spalten.
Hinweis: Mit den richtigen CSS-Stylings können Zellen auch spaltenübergreifend zusammengefasst werden, z.B. um eine durchgehende Footer-Zeile zu erzeugen.
Code des Beispiels
let projectCostumers := (select Kunden);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "MitEinerGruppe" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in Projekte.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: if Projekte then
{
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Nr
}]
}]
}
end,
value: Projekte.Projektname
}, {
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(unique(projectCostumers.Projekte)) + " Projekte"
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let projectCostumers := (select Kunden);
GIP_table({
uniqueId: "MitEinerGruppe" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Projekt"
}, {
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in Projekte.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: if Projekte then
{
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Projekte.Nr
}]
}]
}
end,
value: Projekte.Projektname
}, {
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(unique(projectCostumers.Projekte)) + " Projekte"
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Mehrere Gruppenebenen
Beschreibung
Wir möchten eine Table bauen, in der wir Projekt-Aufgaben anzeigen mit Informationen zum Kunden, Projekt, Verantwortlichen, Priorität und Status der Aufgabe. Für eine bessere Übersichtlichkeit möchten wir nach dem Kunden und dem Projekt gruppieren.
Wir beginnen wie im Beispiel zur Gruppierung auf einer Ebene und erzeugen für jeden Kunden eine Gruppe im Array of Objects von groups.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{ }]
},
}Nun übergeben wir aber keine rows innerhalb der einzelnen Kundengruppen, sondern eine weitere Ebene an groups. In dieser Untergruppen-Ebene erzeugen wir für jedes Projekt des Kunden ein Object, das wir mit denselben Optionen einstellen können, wie die erste Gruppierungsebene.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{ }],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{ }]
},
},
}Erst in der Untergruppe übergeben wir jeweils die Projektaufgaben in rows.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{ }],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{ }],
rows: [{ }]
},
},
}Diese Verschachtelung von Gruppen und Untergruppen kann unendlich häufig fortgesetzt werden.
Code des Beispiels
let projectCostumers := (select Kunden);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "MehrereGruppenebenen" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in project.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let projectCostumers := (select Kunden);
GIP_table({
uniqueId: "MehrereGruppenebenen" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in project.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Spaltenübergreifende Zellen

Beschreibung
In einer Tabelle mit Gruppen möchten wir die Spalten der Gruppenzeilen zusammenfassen, um z.B. längere Texte darin darstellen zu können. Das folgende Vorgehen kann auch auf Footer übertragen werden.
Wir definieren wie üblich unsere 5 Spalten in den headerColumns, um für die Tabelle allgemeine Spaltenbreiten festzulegen. In den groupColumns definieren wir im Gegensatz zum normalen Vorgehen nun aber nur eine einzige Spalte (ein Object im Array). Dieser einzelnen Spalte geben wir folgendes Styling:
groupColumns: [{
style: "grid-column: 1 / -1; text-align: center;",
clickToCollapse: true,
value: let splitValue := split(Kundenname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Kundenname, 0, countSplitValue / 2), 50, "~") + rpad(slice(Kundenname, countSplitValue / 2, countSplitValue) + " ", 50, "~")
}],Der CSS-Style "grid-column" ermöglicht es uns, eine Spannweite der Zelle zu definieren. In diesem Beispiel übergeben wir den Startindex der Zelle ("1", da wir in der ersten Spalte starten möchten) und den Endpunkt der Zelle. Der Endpunkt "-1" bedeutet, dass die Zelle die komplette Breite einnehmen soll, unabhängig von der tatsächlich Spaltenanzahl.
Weitere Infos, wie man mit "grid-column" Spalten zusammenführen kannst, findest du beispielsweise hier.
Code des Beispiels
let projectCostumers := (select Kunden);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Kundenname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Kundenname, 0, countSplitValue / 2), 50, "~") +
rpad(slice(Kundenname, countSplitValue / 2, countSplitValue) + " ", 50, "~")
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Projektname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Projektname, 0, countSplitValue / 2), 50, "+") +
rpad(slice(Projektname, countSplitValue / 2, countSplitValue) + " ", 50, "+")
}],
rows: for task in project.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let projectCostumers := (select Kunden);
GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Kundenname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Kundenname, 0, countSplitValue / 2), 50, "~") +
rpad(slice(Kundenname, countSplitValue / 2, countSplitValue) + " ", 50, "~")
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Projektname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Projektname, 0, countSplitValue / 2), 50, "+") +
rpad(slice(Projektname, countSplitValue / 2, countSplitValue) + " ", 50, "+")
}],
rows: for task in project.Aufgaben do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Checkboxen
Beschreibung
Wir möchten in einer Tabelle Checkboxen einbauen, um einzelne Aufgaben, ganze Gruppen und die komplette Table abhaken zu können.
Um überhaupt Checkboxen in unserer Table anzeigen zu können müssen wir für den Key showCheckboxes entweder true oder ein Object mit selbst festgelegten Checkbox-Icons übergeben.
GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
showCheckboxes: true,
})Danach können wir entscheiden, auf welchen Ebenen wir Checkboxen anzeigen möchten: Header, Groups, Rows. In allen Ebenen, in denen Checkboxen angezeigt werden sollen, übergeben wir den Key checkbox mit einem Object. Dieses Object enthält jeweils Informationen zu einem Ninox-Feld, das durch die Checkbox aktualisiert werden soll. In den Rows, also unseren Aufgaben, ist dies ein 'Ja / Nein'-Ninox-Feld, da Checkboxen für Rows nur zwei Stati haben können: true oder false.
rows: for task in project.Aufgaben do
task.{
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Toggle für Checkbox-Status"),
value: 'Toggle für Checkbox-Status'
},
}Für Gruppen und Header kommt noch ein weiterer Status hinzu: Indeterminate, der als Zahlwert "2" von der Table an Ninox übergeben wird. Dieser wird gesetzt, wenn nur ein Teil der Aufgaben abgehakt ist. Um diese drei Stati abbilden zu können, brauchen Groups, also unsere Kunden und Projekte, jeweils ein Text- oder Zahlfeld. Dasselbe gilt für den Header.
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
}header: {
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
}Die Table hat nun Checkboxen und aktualisiert den Status in den jeweils verknüpften Ninox-Feldern. Allerdings möchten wir ja z.B. beim Aktualisieren eines Projektes auch alle dazugehörigen Aufgaben aktualisieren. Dieses Massenupdate muss Ninox-seitig gebaut werden, da hier die Performance mit dem Befehl "do as transaction" beschleunigt werden kann.
Für das Zahlfeld der Header Checkbox sieht der Trigger nach Änderung wie folgt aus:
do as transaction
let allCostumers := (select Kunden);
switch 'Zahlfeld für Checkbox-Status' do
case 0:
(
allCostumers.('Zahlfeld für Checkbox-Status' := 0);
allCostumers.Projekte.('Zahlfeld für Checkbox-Status' := 0);
allCostumers.Projekte.Aufgaben.('Toggle für Checkbox-Status' := 0)
)
case 1:
(
allCostumers.('Zahlfeld für Checkbox-Status' := 1);
allCostumers.Projekte.('Zahlfeld für Checkbox-Status' := 1);
allCostumers.Projekte.Aufgaben.('Toggle für Checkbox-Status' := 1)
)
case 2:
void
end
endTrigger nach Änderung auf Kunden-Ebene:
do as transaction
switch 'Zahlfeld für Checkbox-Status' do
case 0:
(
Projekte.('Zahlfeld für Checkbox-Status' := 0);
Projekte.Aufgaben.('Toggle für Checkbox-Status' := 0)
)
case 1:
(
Projekte.('Zahlfeld für Checkbox-Status' := 1);
Projekte.Aufgaben.('Toggle für Checkbox-Status' := 1)
)
case 2:
void
end
endTrigger nach Änderung auf Projekt-Ebene:
do as transaction
switch 'Zahlfeld für Checkbox-Status' do
case 0:
Aufgaben.('Toggle für Checkbox-Status' := 0)
case 1:
Aufgaben.('Toggle für Checkbox-Status' := 1)
case 2:
void
end
endCode des Beispiels
let projectCostumers := (select Kunden);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
showCheckboxes: true,
header: {
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
groupColumns: [{
style: "grid-column: 2 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Kundenname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Kundenname, 0, countSplitValue / 2), 50, "~") +
rpad(slice(Kundenname, countSplitValue / 2, countSplitValue) + " ", 50, "~")
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
groupColumns: [{
style: "grid-column: 2 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Projektname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Projektname, 0, countSplitValue / 2), 50, "+") +
rpad(slice(Projektname, countSplitValue / 2, countSplitValue) + " ", 50, "+")
}],
rows: for task in project.Aufgaben do
task.{
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Toggle für Checkbox-Status"),
value: 'Toggle für Checkbox-Status'
},
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let projectCostumers := (select Kunden);
GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
showCheckboxes: true,
header: {
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
groupColumns: [{
style: "grid-column: 2 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Kundenname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Kundenname, 0, countSplitValue / 2), 50, "~") +
rpad(slice(Kundenname, countSplitValue / 2, countSplitValue) + " ", 50, "~")
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Zahlfeld für Checkbox-Status"),
value: 'Zahlfeld für Checkbox-Status'
},
groupColumns: [{
style: "grid-column: 2 / -1; text-align: center;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: let splitValue := split(Projektname, "");
let countSplitValue := cnt(splitValue);
lpad(" " + slice(Projektname, 0, countSplitValue / 2), 50, "+") +
rpad(slice(Projektname, countSplitValue / 2, countSplitValue) + " ", 50, "+")
}],
rows: for task in project.Aufgaben do
task.{
style: "",
checkbox: {
recordId: Nr,
fieldId: fieldId(this, "Toggle für Checkbox-Status"),
value: 'Toggle für Checkbox-Status'
},
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Custom Styling

Beschreibung
Wir möchten statt dem Default-Styling der GIP-Table ein eigenes Styling festlegen, welches im globalen CSS definiert werden soll.
Wir legen zunächst eine Custom CSS-Class für die Table selbst fest, wo wir in diesem Beispiel eine feste Höhe vergeben. Danach folgen je nach Bedarf die Classen für Header, Body, Groups, Rows und Footer.
Interessant ist dabei, dass wir auch Attribute konditionell überschreiben können, z.B. die background-color der Rows. Zunächst legen wir eine allgemeine Hintergrundfarbe für Rows fest:
.customRow {
background-color: #FCFCFC;
}Da wir aber die Zeilen alternierend in einem helleren und einem dunkleren grau färben möchten definieren wir danach:
.customBody .GIPTableDummyRow[data-row-index]:nth-child(even) .GIPTableRow {
background-color: #F5F5F5;
}Hiermit geben wir an, dass wir in unserem customBody jede zweite Dummy-Row (geradzahlig) nehmen wollen. Für jede dieser ausgewählten Rows definieren wir nun die background-color in einem dunkleren grau.
Beachte bei der Definition immer die Reihenfolge von CSS-Klassen. Außerdem gilt auch für deine Custom Classes, dass Inline-Styles über den style-Key diese CSS-Deklarationen überschreiben können. Weitere Infos findest zu im Kapitel "Globaler CSS-Code".
Code des Beispiels
---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.customTable {
height: 500px;
}
.customHeader {
text-transform: uppercase;
background-color: #5F7EBA;
color: white;
}
.customBody {
border-color: white;
}
.customGroup {
font-weight: 600;
}
.customRow {
background-color: #FCFCFC;
}
.customBody .GIPTableDummyRow[data-row-index]:nth-child(even) .GIPTableRow {
background-color: #F5F5F5;
}
.customBody .GIPTableColumn {
padding-left: 12px;
padding-right: 12px;
}
.customFooter {
background-color: #5F7EBA;
color: white;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
let projectCostumers := (select Kunden);
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: false,
class: "customTable",
style: "",
header: {
class: "customHeader",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "customBody",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "customGroup",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "customGroup",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}],
rows: for task in project.Aufgaben do
task.{
class: "customRow",
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "customFooter",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))---
############### Füge den folgenden CSS-Code in die globale Funktion "GIP_customCSS()" ein und lade Ninox neu: ###############
---;
"
.customTable {
height: 500px;
}
.customHeader {
text-transform: uppercase;
background-color: #5F7EBA;
color: white;
}
.customBody {
border-color: white;
}
.customGroup {
font-weight: 600;
}
.customRow {
background-color: #FCFCFC;
}
.customBody .GIPTableDummyRow[data-row-index]:nth-child(even) .GIPTableRow {
background-color: #F5F5F5;
}
.customBody .GIPTableColumn {
padding-left: 12px;
padding-right: 12px;
}
.customFooter {
background-color: #5F7EBA;
color: white;
}
";
---
############### Füge den folgenden Code in dein Ninox-Formelfeld ein: ###############
---;
let projectCostumers := (select Kunden);
GIP_table({
uniqueId: "SpaltenübergreifendeZellen" + Nr,
embedded: true,
class: "customTable",
style: "",
header: {
class: "customHeader",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "customBody",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: for costumer in projectCostumers do
costumer.{
collapseChildren: true,
collapsible: true,
class: "customGroup",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Kundenname
}],
groups: for project in costumer.Projekte do
project.{
collapseChildren: true,
collapsible: true,
class: "customGroup",
style: "",
groupColumns: [{
style: "grid-column: 1 / -1;",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}],
rows: for task in project.Aufgaben do
task.{
class: "customRow",
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "customFooter",
style: "",
footerColumns: [{
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben) + " Aufgaben"
}, {
style: "",
value: cnt(unique(projectCostumers.Projekte.Aufgaben.Verantwortlicher)) +
" Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(projectCostumers.Projekte.Aufgaben[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Gruppierte und Ungruppierte Rows

Beschreibung
Wir haben eine Tabelle, in der wir Aufgaben auf erster Ebene nach Verantwortlichem und auf zweiter Ebene nach Projekt gruppieren. Allerdings gibt es auch Aufgaben ohne Verantwortlichen sowie Aufgaben mit Verantwortlichem, aber ohne Projekt.
Alle Aufgaben ohne Verantwortlichen stellen wir als normale Zeilen ohne Gruppierung dar. Dafür übergeben wir im body wie gewohnt den rows Key, wobei wir durch die Aufgaben ohne Verantwortlichen iterieren.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {...},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end
}Zusätzlich übergeben wir im body auch den groups Key auf gleicher Ebene, wie die gerade angelegten rows. Auf dieser ersten Gruppenebene übergeben wir die Mitarbeiter / Verantwortlichen.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {...},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end,
groups: for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...]
}
end
}Mit diesem Aufbau zeigen wir nun in der Table zuerst die nicht gruppierten Zeilen (Aufgaben ohne Verantwortlichen) an und danach die Gruppen (Verantwortliche).
Für den Inhalt der ersten Gruppierungsebene wiederholen wir das Vorgehen. Wir haben pro Verantwortlichem Aufgaben, die keinem Projekt zugeordnet sind, und Projekte, die die zweite Gruppierungsebene ergeben.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end,
groups: for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [...]
}
end,
groups: for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
}
end
}
end
}Schließlich übergeben wir für unsere zweite Gruppierungsebene auch noch die Aufgaben mit Projektzuordnung und Verantwortlichem.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end,
groups: for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [...]
}
end,
groups: for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [...]
}
end
}
end
}
end
}Code des Beispiels
let teamMembers := (select Mitarbeiter);
let allTasks := (select Aufgaben);
let tasksNotAssigned := allTasks[not Verantwortlicher];
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "GruppierteUndUngruppierteRows" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end,
groups: for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Name
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end,
groups: for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(allTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(teamMembers)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(allTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let teamMembers := (select Mitarbeiter);
let allTasks := (select Aufgaben);
let tasksNotAssigned := allTasks[not Verantwortlicher];
GIP_table({
uniqueId: "GruppierteUndUngruppierteRows" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end,
groups: for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Name
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end,
groups: for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end
}
end
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(allTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(teamMembers)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(allTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})Table: Pseudogruppen

Beschreibung
Wir haben eine Tabelle, in der wir Aufgaben auf erster Ebene nach Verantwortlichem und auf zweiter Ebene nach Projekt gruppieren. Allerdings gibt es auch Aufgaben ohne Verantwortlichen sowie Aufgaben mit Verantwortlichem, aber ohne Projekt.
Alle Aufgaben ohne Verantwortlichen stellen wir in einer manuell angelegten Pseudogruppe dar. Dafür übergeben wir im body wie gewohnt den groups Key, bauen unser Array of Objects aber aus zwei Teilen auf. Zuerst bauen wir unsere Pseudogruppe auf, indem wir ein Array mit nur einem Object auf eine Variable schreiben. In dieser Pseudogruppe durchlaufen wir alle Aufgaben ohne Verantwortlichen und erstellen für diese die rows.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {...},
groups: let pseudoTeamMemberGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end
}];
}Danach bauen wir in einer zweiten Variable die tatsächlich existierenden Gruppen auf, indem wir durch die Mitarbeiter iterieren. Nachdem wir nun sowohl die Pseudogruppe als ein Array mit einem Object, als auch die Verantwortlichen-Gruppen als Array mit vielen Objects angelegt haben, fassen wir diese mit dem Ninox-Befehl "array()" zusammen. Dadurch erhalten wir ein einziges Array ob Objects, für unseren groups-Key.
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {...},
groups: let pseudoTeamMemberGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [...]
}
end
}];
let teamMemberGroups := for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
groups: [...]
}
end;
array(pseudoTeamMemberGroup, teamMemberGroups)
}Dieses Vorgehen, nicht zugeordnete Einträge in einer Pseudogruppe anzulegen, können wir nun gleich noch einmal verwenden. In den Verantwortlichen-Gruppen möchten wir nun nämlich auch noch nach Projekten gruppieren. Doch es kann auch Aufgaben geben, die zwar dem Verantwortlichen zugordnet sind, aber keinem Projekt haben. Daher erstellen wir innerhalb der Verantwortlichen wieder zur Definition der groups zuerst eine Variable für eine Pseudogruppe, bevor wir die tatsächlichen Projekt-Gruppen erstellen.
let teamMemberGroups := for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
groups: let pseudoProjectGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [...]
}
end
}];
let projectGroups := for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [...],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [...]
}
end
}
end;
array(pseudoProjectGroup, projectGroups)
}
end;Dieses Beispiel kann erweitert werden, um beliebig viele Pseudogruppen oder andere Arten von manuellen Gruppierungen zu erzeugen.
Code des Beispiels
let teamMembers := (select Mitarbeiter);
let allTasks := (select Aufgaben);
let tasksNotAssigned := allTasks[not Verantwortlicher];
html(raw(GIP_master({})) +
raw(GIP_table({
uniqueId: "PseudoGruppen" + Nr,
embedded: false,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: let pseudoTeamMemberGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: "Aufgaben ohne Verantwortlichen"
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}];
let teamMemberGroups := for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Name
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
groups: let pseudoProjectGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: "Aufgaben ohne Projekt-Zuweisung"
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}];
let projectGroups := for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end;
array(pseudoProjectGroup, projectGroups)
}
end;
array(pseudoTeamMemberGroup, teamMemberGroups)
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(allTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(teamMembers)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(allTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})))let teamMembers := (select Mitarbeiter);
let allTasks := (select Aufgaben);
let tasksNotAssigned := allTasks[not Verantwortlicher];
GIP_table({
uniqueId: "PseudoGruppen" + Nr,
embedded: true,
class: "",
style: "height: 500px;",
header: {
class: "",
style: "",
headerColumns: [{
style: "",
columnWidth: "2fr",
value: "Aufgabe"
}, {
style: "",
columnWidth: "1fr",
value: "Verantwortlicher"
}, {
style: "",
columnWidth: "1fr",
value: "Priorität"
}, {
style: "",
columnWidth: "1fr",
value: "Status"
}]
},
body: {
class: "",
style: "",
rowHeight: "40px",
placeholder: {
style: "",
value: "Es wurden keine Daten gefunden, die auf die aktuellen Filter zutreffen."
},
groups: let pseudoTeamMemberGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: "Aufgaben ohne Verantwortlichen"
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNotAssigned in tasksNotAssigned do
taskNotAssigned.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}];
let teamMemberGroups := for teamMember in teamMembers do
teamMember.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Kunde öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Name
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
groups: let pseudoProjectGroup := [{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: "Aufgaben ohne Projekt-Zuweisung"
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for taskNoProject in teamMember.Aufgaben[not Projekte] do
taskNoProject.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}];
let projectGroups := for project in unique(teamMember.Aufgaben.Projekte) do
project.{
collapseChildren: true,
collapsible: true,
class: "",
style: "",
groupColumns: [{
style: "",
clickToCollapse: true,
hoverElement: {
class: "",
style: "",
value: "Projekt öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Projektname
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}, {
clickToCollapse: true,
style: "",
value: ""
}],
rows: for task in teamMember.Aufgaben[Projekte = project] do
task.{
style: "",
columns: [{
style: "",
hoverElement: {
class: "",
style: "",
value: "Aufgabe öffnen",
actions: [{
trigger: "click",
scripts: [{
type: "popup",
recordId: Nr
}]
}]
},
value: Bezeichnung
}, {
style: "",
value: Verantwortlicher.Name
}, {
style: "",
value: text('Priorität')
}, {
style: "",
value: Status.Bezeichnung
}]
}
end
}
end;
array(pseudoProjectGroup, projectGroups)
}
end;
array(pseudoTeamMemberGroup, teamMemberGroups)
},
footer: {
class: "",
style: "",
footerColumns: [{
style: "",
value: cnt(allTasks) + " Aufgaben"
}, {
style: "",
value: cnt(unique(teamMembers)) + " Verantwortliche"
}, {
style: "",
value: ""
}, {
style: "",
value: cnt(allTasks[number(Status) = 5]) + " Abgeschlossen"
}]
}
})