Custom Table

Die Custom Table besteht aus einem Anwendungscode, den du in einem Ninox Formel-Feld auf deiner Wunschoberfläche in der Datenbank einfügst. Dieser besteht aus einem allgemeinen Part (settings), in dem du Grundeinstellungen vornimmst und einem Detail-Bereich (table), in dem du deine Tabelle individuell gestalten und befüllen kannst. (Farben, Werte, Aktionen …)
Gesamter Anwendungscode
Folgend siehst du einen beispielhaften Anwendungscode, der die Basis deiner Custom Table definiert. Da der Code bei der Custom Table sehr umfassend werden kann, leiten wir dich von simpel zu komplex durch.
Mit data definierst du die Inhalte deiner Tabelle. Mit der globalen Funktion arcCustomTable() gibst du dann diese Daten aus.
let current := this;
let projectList := (select Projekte);
let data := {
uniqueListId: "Projektliste Offen",
tableId: tableId(first(projectList)),
height: "500px",
groupedBy: "",
theme: "cleanSeamless",
popupButtonTitle: "Open",
table: projectList.[{
recordId: Nr,
rowColor: "",
rowHeight: "auto",
groupRowColor: "",
columns: [{
field: "Feldname für Feld-ID",
title: "Titel",
value: "Ninox Wert",
width: "10%"
}, {
field: "Bezeichnung",
title: "Projekt",
value: Bezeichnung,
width: "15%",
actions: [{
type: "popup",
recordId: Nr
}, {
type: "change",
recordId: Nr,
field: "A"
}]
}, {
field: "Umsatz",
title: "Umsatz",
value: text(Umsatz + 1000),
width: "20%"
},]
}],
footer: {
showFooter: false,
actionButtonTitle: "",
rightSideContent: "Gesamt: " + cnt(projectList) + " Projekte"
}
};
arcCustomTable(data)
Allgemeine Settings
In den allgemeinen Settings nimmst du die Grundeinstellungen deiner Tabelle vor. Diese wirkt sich auf alle Spalten und Zeilen deiner Tabelle aus. Folgend werden dir die einzelnen Parameter erläutert:
uniqueListID ist die individuelle Bezeichnung deiner Tabelle. Achte darauf, dass du hier einen einzigartigen Titel vergibst. Das ist wichtig, falls du mehrere Tabellen auf einer Seite darstellen möchtest und deine Style-Einstellungen nur für diese Tabelle gelten sollen.
uniqueListId: "Projektliste Offen",
tableID gibt die ID deiner darzustellenden Tabelle an.
tableId: tableId(first(projectList)),
height gibt die Höhe deiner Tabelle an.
groupedBy gibt den Wert (Titel der Spalte/Feld) an, nach dem gruppiert werden soll. Trägst du nichts ein in die "", so wird nach nichts gruppiert.
groupedBy: "",
groupedby: "Status",
groupedBy: Gruppierung,
theme ist ein vorgefertigtes Design / Gestaltungsvorlage, die bestimmt, wie deine Tabellen-Oberfläche in Bezug auf Farben, Schriftarten, Layout und andere Design-Elemente aussieht. Mehr dazu findest du unter dem Reiter Themes.
Footer der Tabelle
footer definiert, ob du einen unteren Bereich deiner Tabelle definieren möchtest. Hier kannst du auch Aktionen hinzufügen.
footer: {
showFooter: true,
showActionButton: true,
actionButtonTitle: "Neue Aufgabe hinzufügen",
rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben"
}
So sieht der oben definierte Footer aus:

showFooter definiert, ob ein Footer angezeigt wird oder nicht.
showFooter: true,
showFooter: false,
showActionButton definiert ob ein Aktions Button angezeigt wird oder nicht. Die Aktion bedeutet immer, dass ein neuer Datensatz in der referenzierten Tabelle erstellt wird. (create record)
showActionButton: true,
showActionButton: false,
actionButtonTitle definiert den Text innerhalb deines Buttons.
actionButtonTitle: "Neue Aufgabe hinzufügen",
rightSideContent definiert, was auf der rechten Seite deines Footers stehen soll. Hier bist du frei in der Gestaltung.
rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben"
Standard-Werte als Fallback
💡 Hinweis: Alle Werte der Parameter werden in Anführungszeichen angegeben. Trägst du nichts in die Anführungszeichen ein, so greift das System auf ein Fallback zurück, der im globalen Code definiert ist. Das heißt es gibt voreingestellte Standard-Werte, sodass immer etwas ausgegeben wird. Hier siehst du den Code der Standard-Werte:
uniqueListId: "",
tableId: "",
height: "",
groupedBy: "",
theme: "",
popupButtonTitle: "",
table: projectList.[{
recordId: "",
rowColor: "",
rowHeight: "",
groupRowColor: "",
showFooter: "",
showActionButton: "",
actionButtonTitle: "",
rightSideContent: ""
field: "",
title: "",
value: "",
width: "",
align: "",
fixed: "",
actions: [{
recordId: "",
type: "",
field: "",
value: "",
headerAction: ""
}],
groupValue: ""
Detail-Bereich
Im Detail-Bereich (table) definierst du alle Styles und Werte deiner Tabellenspalten & -inhalte. Das heißt: Jede Spalte kann individuell gestaltet werden. Die Styles überschreiben in dem Fall die Werte aus den Allgemeinen Settings.
table: projectList.[{
recordId: Nr,
rowColor: "",
rowHeight: "auto",
groupRowColor: "",
rowHeight kannst du in folgenden Werten angeben:
rowHeight: "50px",
rowHeight: "auto",
groupRowColor kannst du in folgenden Werten angeben:
groupRowColor: "#444363",
groupRowColor: if cnt(Firma.Projekte) = cnt(Firma.Projekte[Abgeschlossen != null]) then
"#F0FFF1"
else
"#eee"
end,
groupRowColor: text(color(Auswahlfeld))
columns definiert deine einzelnen Spalten in der Tabelle. Folgend siehst du die Basics, die du einstellen kannst.
columns: [{
field: "Feldname für Feld-ID",
title: "Titel",
value: "Ninox Wert",
width: "10%"
}
Parameter für die Spalten
Die Custom Table kann um einiges komplexer und individueller gestaltet werden. Folgend werden dir alle Parameter aufgelistet, die du bei columns einsetzen und definieren kannst.
field: "",
title: "",
value: "",
width: "",
align: "",
fixed: "",
actions: [{
recordId: "",
type: "",
field: "",
value: "",
headerAction: ""
}],
groupValue: ""
Align
align gibt an wie sich dein Inhalt innerhalb der Zelle ausrichtet. Du hast folgende Möglichkeiten:
align: "left",
align: "center",
align: "right",
Fixed
fixed gibt an, ob deine Spalte am Rand haften bleiben soll und somit immer sichtbar ist. Scrollst du bei vielen Inhalten in der Tabelle nach rechts, bleibt deine gefixte Leiste immer sichtbar.
fixed: "left",
fixed: "reight",
Aktionen
Du kannst für deine Zellen-Werte drei verschiedene Aktionen ausführen: popup, delete und update. Der Grundschreibweise einer Aktion wird wie folgt geschrieben:
actions: [{
recordId: "",
type: "",
field: "",
value: "",
headerAction: ""
}],
💡 Hinweis: Du kannst auch mehrere Aktionen auf einem Feld ausführen. Diese trennst du durch ein Komma (,). Zum Beispiel so:
actions: [{
recordId: Nr,
type: "popup"
}, {
recordId: Nr,
type: "change",
field: "A"
}],
Aktion Popup
type: "popup" öffnet einen Record. Diese Funktion wirkt sich auf jede einzelne Zelle aus.
actions: [{
recordId: Nr,
type: "popup"
}]
Aktion Delete
type: "delete" löscht einen Record. Diese Funktion wirkt sich auf jede einzelne Zelle aus.
actions: [{
recordId: Nr,
type: "delete"
}]
Aktion Update
type: "update" öffnet einen Record. Diese Funktion wirkt sich auf jede einzelne Zelle aus.
actions: [{
recordId: Nr,
type: "update",
field: "G",
value: if erledigt=true then null else true end,
headerAction: ""
}]
💡 Hinweis: Um die Ninox Feld-ID bestimmter Felder herauszufinden, gibt es zwei Möglichkeiten:
Du Trägst den richtigen Feldnamen bei dem Parameter field ein. Nach dem Speichern wird dir die Feld-ID in der Kopfzeile deiner Tabelle angezeigt. Achte darauf, dass der field Inhalt exakt so geschrieben ist, wie der Ninox Feldname. Andernfalls wird die ID nicht angezeigt. Außerdem werden die Feldnamen nur ausgegeben, wenn du im Bearbeitungsmodus bist.
2. Du verwendest die nützliche Funktion arcFieldFinder().
Group Value
groupValue gibt den Wert/Inhalt an, der bei einer Gruppierung angezeigt wird.
groupValue: Projekte.Bezeichnung
groupValue: "Projekt:" + Projekte.Bezeichnung
Beispiele
Folgend findest du einige Praxisbeispiele, die dir den unterschiedlichen Einsatz der Custom Table veranschaulichen.
Custom Table Simple

let current := this;
let projectList := (select Projekte);
let data := {
uniqueListId: "Projektliste Offen",
tableId: tableId(first(projectList)),
maxHeight: "500px",
minHeight: "400px",
groupedBy: "",
theme: "seamlessWhite",
popupButtonTitle: "Open",
table: projectList.[{
recordId: Nr,
rowColor: "",
groupRowColor: "#eee",
columns: [{
field: "Feldname für Feld-ID",
title: "Titel",
value: "Ninox Wert",
width: "10%"
}, {
field: "Feldname für Feld-ID",
title: "Titel",
value: "Ninox Wert",
width: "15%"
}, {
field: "Feldname für Feld-ID",
title: "Titel",
value: "Ninox Wert",
width: "10%"
}, {
field: "Firma.Name",
title: "Firma",
value: Firma.Name,
width: "10%"
}, {
field: "Bezeichnung",
title: "Projekt",
value: Bezeichnung,
width: "15%",
actions: [{
type: "popup",
recordId: Nr
}, {
type: "change",
recordId: Nr,
field: "A"
}]
}, {
field: "Umsatz",
title: "Umsatz",
value: text(Umsatz + 1000),
width: "20%"
}, {
field: "Aufgaben",
title: "Status Aufgaben",
value: "<h1>",
width: "100px"
}, {
field: "Abgeschlossen",
title: "Abgeschlossen am",
value: text(Abgeschlossen),
width: "100px"
}]
}],
footer: {
showFooter: false,
actionButtonTitle: "",
rightSideContent: "Gesamt: " + cnt(projectList) + " Projekte"
}
};
arcCustomTable(data)
Custom Table Complex

let current := this;
let data := {
height: "100px",
loading: "Loading"
};
arcCustomTable(data);
let list := do as transaction
select Aufgaben
end;
let filteredList := list[if current.Suche != null then
testx(Mitarbeiter.'First Name' + "," + text(Mitarbeiter.'Last Name') + "," +
text(Aufgabe) +
"," +
text(Projekte.Bezeichnung) +
"," +
"", "(?:" + current.Suche + ")\.*[^]", "gi")
else
true
end and
if current.'Erledigte einblenden' = true then
true
else
Erledigt != true
end];
let data := {
uniqueListId: "Projektliste A",
tableId: tableId(first(list)),
height: "500px",
theme: "",
groupedBy: text('Gruppieren nach'),
embedded: false,
table: filteredList.[{
recordId: Nr,
rowColor: "",
rowHeight: "60px",
groupRowColor: let currentRecord := this;
if cnt(filteredList[Projekte.Bezeichnung = currentRecord.Projekte.Bezeichnung and Erledigt = true]) = cnt(filteredList[Projekte.Bezeichnung = currentRecord.Projekte.Bezeichnung]) then
"#dcf2de"
else
"#eee"
end,
columns: [{
field: "Erledigt",
title: arcCheckBox(if cnt(list[Erledigt = true]) != cnt(list) then
false
else
if cnt(list[Erledigt = null]) = cnt(list) then
null
else
if cnt(list[Erledigt = true]) = cnt(list) then
true
end
end
end),
value: arcCheckBox(Erledigt),
width: "40px",
align: "center",
fixed: "left",
actions: [{
recordId: Nr,
type: "update",
field: "D",
value: if Erledigt = true then null else true end,
headerAction: true
}],
groupValue: iconPhosphor("caret-circle-double-down-fill", "#555", 20, 20)
}, {
field: "Bild",
title: "Logo",
width: "150px",
value: arcCustomImage(text(Projekte.'Bild URL'), "100px", "100px", "cover", "", ""),
actions: [{
recordId: Projekte.Nr,
type: "popup"
}],
groupValue: arcCustomImage(text(Projekte.'Bild URL'), "50px", "50px", "cover", "", "border-radius:50%")
}, {
field: "Projekt",
title: "Projekt",
width: "",
value: Projekte.Bezeichnung,
actions: [{
recordId: Projekte.Nr,
type: "popup"
}],
groupValue: Projekte.Bezeichnung
}, {
field: "Aufgaben",
title: "Aufgabe",
value: Aufgabe,
align: "left",
width: "200px",
actions: [{
recordId: Nr,
type: "popup"
}, {
recordId: Nr,
type: "change",
field: "A"
}],
groupValue: if current.'Gruppieren nach' = 3 then
html(---
<b>{ Aufgabe }</b>
---)
end
}, {
field: "Mitarbeiter",
title: "Mitarbeiter",
value: arcBadgeSimple(Mitarbeiter.'First Name', "", ""),
actions: [{
recordId: Mitarbeiter.Nr,
type: "popup"
}],
groupValue: if current.'Gruppieren nach' = 2 then
arcBadgeSimple(Mitarbeiter.'First Name', "", "")
end
}, {
field: "delete",
title: iconPhosphor("trash", "#E9595D", 20, 20),
width: "40px",
align: "center",
value: iconPhosphor("trash", "#E9595D", 20, 20),
actions: [{
recordId: Nr,
type: "delete"
}]
}]
}],
footer: {
showFooter: true,
showActionButton: true,
actionButtonTitle: "Neue Aufgabe hinzufügen",
rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben"
}
};
arcCustomTable(data)
Weiterführende Links:
> NX Custom Table