Widgets

Custom Table

2.4.0

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); // Hier definierst du, welche Datensätze in deiner Custom Table verwendet werden sollen.
let data := {
		uniqueListId: "Projektliste Offen",
		tableId: tableId(first(projectList)),
		height: "500px",
        groupedBy: "",
		theme: arcCustomThemeCleanWhite({
					uniqueId: "Projektliste Demo 1"
				}),
		embedded: false,
  		rowHoverAction: {
			hoverActive: true,
			backgroundColor: "#9ca4a9",
			fontColor: "#fff"
		},
		header: {
			showHeader: true,
			height: "70px",
			fontColor: "#fff",
			backgroundColor: "#3a4a54",
			fontSize: "17px"
		},
		emptyTable: {
			title: "Keine Projekte gefunden"
		},
		scrollBar: {
			showScrollBar: true,
			height: "20px",
			backgroundColor: "#3a4a54",
			handle: {
				height: "8px",
				borderRadius: "5px",
				backgroundColor: "#fff"
			}
		},
		table: projectList.[{  // Hier wird die oben definierte select-Variable verwendet.
				recordId: Nr, // Dies ist die Ninox Nr eines einzelnen Projektes
				rowColor: "",
                rowHeight: "auto",
                rowPaddingY: "0",
				groupRowColor: "",
				columns: [{
						field: "Feldname für Feld-ID",
						title: "Titel",
						value: "Ninox Wert",
                        color: "",
                        backgroundColor: "#000",
						width: "10%",
                        paddingX: "5px",
                        paddingY: "10px",
					}, {
						field: "Bezeichnung",
						title: "Projekt",
                        backgroundColor: if Erledigt=true then "green" else "#000" end,
                        color: "",
						value: Bezeichnung, 
						width: "15%",
                        paddingX: "0px", // Setze den Padding auf 0 wenn du zum Beispiel ein Custom Layout in eine Spalte einsetzen möchtest.
                        paddingY: "0px",
						actions: [{
								type: "popup",
								recordId: Nr,
                                showPopupButton: true,
								popupButton: arcCustomButton({
										uniqueId: "ButtonProjekt" + Nr,
										icon: "",
										title: "Open",
										fontSize: "13px",
										fontColor: "",
										iconColor: "",
										backgroundColor: "",
										borderColor: ""
									})
							}, {
								type: "change",
								recordId: Nr,
								field: "A"
							}]
					}, {
						field: "Umsatz",
						title: "Umsatz",
						value: text(Umsatz + 1000),
						width: "20%"
					}]
			}],
		footer: {
			showFooter: false,
            showActionButton: true,
			actionButtonTitle: "",
			leftSideContent: arcCustomButton({
					uniqueId: "Button popUp",
					title: "Neues Projekt hinzufügen",
					width: "",
					icon: arcCustomIcon({
							name: "plus-bold",
							color: "#0062AA"
						}),
					fontSize: "",
					fontColor: "#0062AA",
					iconColor: "#0062AA",
					backgroundColor: "#0062AA33",
					borderColor: "#0062AA",
					borderRadius: "50px",
					hoverActions: {
						fontColor: "#ffffff",
						iconColor: "#ffffff",
						backgroundColor: "#0062AA",
						borderColor: "#0062AA",
						animation: "0.8s"
					}, 
					actions: [{
							type: "create",
							tableId: "D",
							popup: true,
							changeFieldValues: [{
									fieldId: "",
									value: ""
								}]
						}]
				}),             
			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", // Text

tableID gibt die ID deiner darzustellenden Tabelle an.

tableId: tableId(first(projectList)), // Ninox Funktion zum Herausfinden der Table ID deiner darzustellenden Tabelle

height gibt die Höhe deiner Tabelle an.

height: "500px", // Pixel Werte

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: "", // keine Gruppierung ausgewählt
groupedby: "Status", // Text des Feldtitels, nach dem gruppiert werden soll 
groupedBy: Gruppierung, // Ninox Feld, das angesprochen wird. In diesem Fall: Ein Auswahlfeld, in dem die Optionen den Titel verschiedener Ninox-felder tragen, nach denen gruppiert werden kann. (z.B. Status, Mitarbeiter, Aufgabe) 

embedded benutzt du, wenn du die Table in einem Layout integrierst und diese somit eingebettet wird. Standardmäßig ist dies aber auf false gesetzt.

embedded: false,
embedded: true, 
embedded: "", // default: false

rowHoverAction Block

Mit dem rowHoverAction Block kannst du bestimmen, ob das hovern über die row angezeigt werden soll und welche Farbe der Hintergrund und welche die Schrift beim hovern haben soll.

rowHoverAction: { hoverActive: true, // wenn hovern an sein soll, und false, wenn nicht
                  backgroundColor: "#9ca4a9", // default: #f4f6ff 
                  fontColor: "#fff" } // default: #000

header Block

Mit dem header Block kannst du mit showHeader: false die header Zeile deiner customTable ausblenden. Außerdem kannst du Höhe, Schriftfarbe, Schriftgröße und Hintergrundfarbe einstellen.

header: { showHeader: false, // default: true
          height: "70px", // default: 50px
          fontColor: "#fff", // default: #000
          backgroundColor: "#3a4a54", // default: #f8f9fc
          fontSize: "17px" } // default: 14px

emptyTable Block

Mit dem emptyTable Block kannst du für deine customTable, mit title den Text bestimmen, der angezeigt werden soll, wenn deine Table keine Werte ausgibt.

emptyTable: { title: "Keine Produkte gefunden..." } // default: "Keine Ergebnisse"

scrollBar Block

Im scrollbar Block kannst duEinstellungen für die vertikale Scrollbar vornehmen. Mit showScrollbar: true kannst du bestimmen, dass die Scrollbar angezeigt werden soll. Außerdem kannst du die Höhe und Hintergrundfarbe des containers sowie die Höhe und Hintergrundfarbe und den borderRadius des handle (Schiebers) bestimmen.

scrollBar: { showScrollbar: true, // default: false (Scrollbar ist standardmäßig ausgeblendet)
              height: 40px, // Höhe des Containers. default: 10px
              backgroundColor: "#3a4a54" // default: #f0f0f0
              handle: { height: "20px", // Höhe des Schiebers. default: 90%
                        borderRadius: 20px // default: 20px
                        backgroundColor: "#fff", } // default: #ccc


theme ist ein vorgefertigtes Design / Gestaltungsvorlage, die bestimmt, wie deine Tabellen-Oberfläche in Bezug auf Farben, Schriftarten, Layout und andere Design-Elemente aussieht. Aktuell gibt es ein alternativen Theme für die Custom Table: Clean White.

theme: arcCustomThemeCleanWhite({
					uniqueId: "Projektliste Demo 1"
				}),

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",
			leftSideContent: "", 
            rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben"
		}

So sieht der oben definierte Footer aus:

showFooter definiert, ob ein Footer angezeigt wird oder nicht.

showFooter: true, // Footer wird angezeigt
showFooter: false, // Footer wird nicht angezeigt

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, // Action Button wird angezeigt
showActionButton: false, // Action Button wird nicht angezeigt

actionButtonTitle definiert den Text innerhalb deines Buttons.

actionButtonTitle: "Neue Aufgabe hinzufügen", // Text

leftSideContent definiert, was auf der linken Seite deines Footers stehen soll. Hier bist du frei in der Gestaltung.

rightSideContent definiert, was auf der rechten Seite deines Footers stehen soll. Hier bist du frei in der Gestaltung.

rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben" // Alle Ninox-Funktionen/-Schreibweisen sowie arcRider Funktionen kannst du hier verwenden.

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:

// ALGEMEIN 

uniqueListId: "", // Kein Fallback
tableId: "", // Kein Fallback
height: "", // Fallback: auto
groupedBy: "", // Kein Fallback 
theme: "", // Kein Fallback. Die Tabelle hat ein Grunddesign. Themes sind optional.
embedded:"", //Fallback: false
popupButtonTitle: "", //Fallback: Öffnen
table: projectList.[{
        recordId: "", // Kein Fallback
        rowColor: "", // Fallback: #FFFFFF
		rowHeight: "", // Fallback: 50px
		groupRowColor: "", // Fallback: #FFFFFF

// FOOTER

showFooter: "", // Fallback: false | Inhalt wird nicht angezeigt 
showActionButton: "", // Fallback: false | Button wird nicht angezeigt
actionButtonTitle: "", // Fallback: Icon Plus
rightSideContent: "" // Fallback: false | kein Inhalte
lefttSideContent: "" // Fallback: false | kein Inhalte

  
  
// PARAMETER

field: "", // Kein Fallback | wenn leer, keine field-ID Anzeige.
title: "", // Kein Fallback | wenn leer, wird nichts angezeigt.
value: "", // Kein Fallback | wenn leer, wird kein Wert angezeigt.
width: "", // Fallback: 100%
align: "", // Fallback: left
backgroundColor: "", // Fallback: transparent
color: "", // Fallback: #262f4d
fixed: "", // Kein Fallback | Feld nicht fixiert.
actions: [{
    recordId: "", // Kein Fallback 
    type: "", // Kein Fallback 
    field: "", // Kein Fallback 
    value: "", // Kein Fallback 
    headerAction: "" // Kein Fallback 
    }],
groupValue: "" // Kein Fallback | es wird nichts angezeigt.

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, // Muss immer die Nr sein. Dies ist wichtig für die Funktionalität des Widgets.
				rowColor: "", // Definiert die Hintergrundfarbe der Zeilen. Benutze HEX Werte (#FFF567)
				rowHeight: "auto", // Definiert Zeilenhöhe.
                groupRowColor: "", // Definiert die Zeilenfarbe der Gruppierung. Du kannst HEX Werte einsetzen oder auch Ninox-Felder ansprechen.

rowHeight kannst du in folgenden Werten angeben:

rowHeight: "50px", // Pixelwerte für fetsgelegte Höhe. 
rowHeight: "auto", // Dynamische Höhe, die sich automatisch an den Inhalt anpasst.

rowPaddingY definiert wie viel padding nach oben und unten in einer Zeile eingestellt werden soll.

rowPaddingY: "0",

groupRowColor kannst du in folgenden Werten angeben:

groupRowColor: "#444363", // HEX Wert für Farbe
groupRowColor: if cnt(Firma.Projekte) = cnt(Firma.Projekte[Abgeschlossen != null]) then
					"#F0FFF1"
				else
					"#eee"
				end, // Ninox Konditionen 
 groupRowColor: text(color(Auswahlfeld)) // Du kannst auch direkt Ninox Felder ansprechen. Achte darauf, dass am Ende immer ein Text-Wert angegeben wird.

columns definiert deine einzelnen Spalten in der Tabelle. Folgend siehst du die Basics, die du einstellen kannst.

columns: [{
						field: "Feldname für Feld-ID", // Genauer Name des Feldes, auf das du dich beziehst.
						title: "Titel", // Gib den Titel deiner Spalte an, der in der obersten Zeile zu sehen ist.
						value: "Ninox Wert", // Ninox-Feld oder Funktionen, die den Wert ausgeben. 
						width: "10%" // Breite deiner Tabellenspalte. Entweder in % ("10%") oder px ("10px").
					}

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", // Inhalt wird linksbündig angeordnet.
align: "center", // Inhalt wird zentriert innerhalb der Zelle.
align: "right", // Inhalt wird rechtsbündig angeordnet.

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", // Fixiert deine Spalte an der linken Seite.

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: "", // Gibt die ID des records an, auf den die AKtion ausgeführt werden soll.
	type: "", // Gibt den Typ der Aktion als text an.
	field: "", // Wird nur bei dem Typ update benötigt und gibt die Field ID des Feldes an, auf das die Aktion angewendet wird.
	value: "", // Wird nur bei dem Typ update benötigt und gibt den Wert an, der geupdated wird. 
	headerAction: "" // Bestimmt, ob der Tabellenkopf auch eine Aktion ausführt.
    }],

💡 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", // Text. Muss genau so geschrieben werden.
  showPopupButton: true, // true oder false zum Ein- oder Ausblenden des Open-Buttons
  popupButton: arcCustomButton({
		uniqueId: "ButtonProjekt" + Nr,
		icon: "",
		title: "Open",
		fontSize: "13px",
		fontColor: "",
		iconColor: "",
		backgroundColor: "",
		borderColor: ""
	})
}]

Aktion Delete

type: "delete" löscht einen Record. Diese Funktion wirkt sich auf jede einzelne Zelle aus.

actions: [{
  recordId: Nr,
  type: "delete" // Text. Muss genau so geschrieben werden.
}]

Aktion Update

type: "update" aktualisiert / manipuliert einen Record. Diese Funktion wirkt sich auf jede einzelne Zelle aus.

actions: [{
  recordId: Nr,
  type: "update", // Text. Muss genau so geschrieben werden.
  field: "G", // Gibt die genaue Field ID des Feldes an, auf das die Aktion angewendet wird.
  value: if erledigt=true then null else true end, // Gibt den Wert an, der bei dem referenzierten Feld eingesetzt werden soll. 
  headerAction: ""  // Gibt an, ob in der Kopfzelle auch diese Aktion ausgeführt wird.
}]

Aktion openFullscreen

type: "openFullscreen" öffnet Datensätze im Fullscreen. Diese Funktion wirkt sich auf jede einzelne Zelle aus.

actions: [{
  recordId: Nr,
  type: "openFullscreen", // Text. Muss genau so geschrieben werden.
}]

💡 Hinweis: Um die Ninox Feld-ID bestimmter Felder herauszufinden, gibt es zwei Möglichkeiten:

  1. 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 // Ninox-Felder & -Schreibweisen möglich
groupValue: "Projekt:" + Projekte.Bezeichnung // Text + Ninox-Feld

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: "",
		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;

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