Widgets

Custom Table

Custom Table

Das Custom Table-Widget ermöglicht dir die Darstellung dynamischer, interaktiver Tabellen direkt auf deiner Ninox-Oberfläche – maßgeschneidert nach deinen Anforderungen. Es eignet sich ideal, um strukturierte Daten übersichtlich darzustellen, individuell zu formatieren und mit Aktionen zu verknüpfen (z. B. für Bearbeiten, Löschen, Öffnen von Datensätzen oder API-Aufrufe).

Beispiel:

🧩 Gesamter Anwendungscode

Im Folgenden siehst du einen beispielhaften Anwendungscode, der die Basis deiner Custom Table definiert. Da der Code – je nach Anwendungsfall – sehr umfangreich werden kann, führen wir dich schrittweise von einer einfachen Basis zu komplexeren Varianten.

Der Aufbau gliedert sich in zwei zentrale Bereiche:

  1. data – definiert den Inhalt und die Struktur deiner Tabelle (Zeilen und Spalten)

  2. arcCustomTable() – ist die globale Funktion, die das Widget rendert. Ihr übergibst du die data

let current := this;
let projectList := Artikel;
let data := {
		uniqueListId: "beispiel" + Nr,
		tableId: "",
		height: "500px",
        minWidth: "", 
		groupedBy: "",
        groupsCollapsed: false, 
		theme: arcCustomThemeCleanWhite({
					uniqueId: "beispiel"
				}), 
		embedded: false,
		rowHoverAction: {
			hoverActive: true,
			backgroundColor: "",
			fontColor: ""
		},
		header: {
			showHeader: true,
			height: "",
			fontColor: "",
			backgroundColor: "",
			fontSize: "",
            columns: [{
					title: "Prio", 
                    width: ""
				}]
		},
		emptyTable: {
			title: "Keine Ergebnisse", 
            backgroundColor: "", 
            value: ""
		},
		scrollBar: {
			showScrollBar: false,
			height: "",
			backgroundColor: "",
			handle: {
				height: "",
				borderRadius: "",
				backgroundColor: ""
			}
		},
		table: projectList.[{
				recordId: Nr,
				rowColor: "",
				rowHeight: "auto",
				rowPaddingY: "10px",
				groupRowColor: "",
                groupRowSettings: {
                    height: "",
                },
				columns: [{
						field: "",
						title: "",
						value: "",
						color: "",
						backgroundColor: "",
						width: "",
                        align: "left",
						paddingX: "",
						paddingY: "", 
                        groupExpandAction: false,
                        groupValue: arcCustomIcon({
								name: "caret-down"
							}),
                        groupByValue: "",
                        actions: [{
								type: "popup",
                                showPopupButton: false, 
								recordId: Nr
							}]
					}]
			}],
		footer: {
			showFooter: false,
			showActionButton: true,
            backgroundColor: "",
			actionButtonTitle: "",
			leftSideContent: "",
			rightSideContent: "Gesamt: " + cnt(projectList) + " Projekte"
		}
	};
arcCustomTable(data)

🔸 uniqueListId

Der Parameter uniqueListId ist die individuelle Bezeichnung deiner Tabelle. Er sorgt dafür, dass deine Tabelle intern eindeutig identifiziert wird – besonders dann, wenn mehrere Tabellen gleichzeitig auf einer Seite angezeigt werden.

Warum ist das wichtig?

  • Style-Einstellungen (z. B. Farben, Schriftarten, Hover-Effekte) werden gezielt nur auf die Tabelle mit der angegebenen uniqueListId angewendet.

  • Bei mehreren Tabellen auf einer Ansicht kann es sonst zu Konflikten bei CSS-Klassen oder Zuständen kommen.

✅ Best Practice:

Verwende sprechende, eindeutige Namen – am besten in camelCase oder mit Unterstrichen.

uniqueListId: "Projektliste Offen", // Text

🔸 tableId

Mit tableId gibst du die interne ID der Tabelle in Ninox an, auf die sich das Widget bezieht. Diese ID wird z. B. benötigt, um:

  • neue Datensätze über den „+“-Button im Footer anzulegen (create)

  • bestehende Datensätze zu öffnen oder bearbeiten zu können (popup, openFullscreen, update)

  • Aktionen korrekt auf Datensätze dieser Tabelle zu beziehen

tableId: "AB", // Die ID als Textform
tableId: tableId("Kontakte"), // Ninox Funktion zum Herausfinden der Table ID deiner darzustellenden Tabelle

🔸 height

Mit height bestimmst du die Höhe des Tabellen-Widgets in Pixeln. So kannst du die Darstellung flexibel an das Layout deiner Seite anpassen – egal, wie viele Daten enthalten sind.

💡 Werte

  • Der Wert wird in Pixeln angegeben – z. B. "300px", "500px" oder "800px".

  • "auto": Die Höhe passt sich automatisch an den Inhalt an. Perfekt für dynamische Inhalte – beachte aber mögliche Sprünge im Layout.

  • In Kombination mit maxHeight kannst du die automatische Höhe begrenzen.

height: "500px", // Pixel Werte

🔸 minWidth

Mit minWidth legst du die minimale Breite deiner Tabelle fest – unabhängig davon, wie viele Spalten oder Daten enthalten sind. So stellst du sicher, dass die Tabelle nicht zu schmal dargestellt wird, z. B. bei schmalen Containern, Tabs oder eingebetteten Ansichten.

🔍 Format

  • Der Wert wird als Text mit Einheit übergeben, z. B. "600px"

  • Ohne Angabe kann die Tabelle bei zu wenig Inhalt schmal zusammenfallen – was das Layout stören kann.

💡 Hinweis:

minWidth wirkt sich auf die äußere Tabellenhülle aus – nicht auf die Spaltenbreiten im Inneren. Für Spalten gibt es separate Optionen wie width und minWidth direkt im columns-Block.

minWidth: "",

🔸 groupedBy

Mit groupedBy definierst du, nach welchem Feld (Spalten-Key bzw. field) deine Tabelle gruppiert werden soll. Gruppen werden dabei visuell als separate Zeilen mit eigener Formatierung dargestellt – die darunterliegenden Einträge lassen sich ein- und ausklappen.

🔍 Verhalten

  • Du gibst hier den Spaltennamen (field) an, der in deinem columns-Block definiert ist.

  • Ist das Feld leer ("") oder fehlt ganz, findet keine Gruppierung statt.

  • Gruppierung kann auch auf komplexen Werten basieren (z. B. Typ, Kategorie, Verantwortlicher etc.).

  • Die Gruppen lassen sich dynamisch durch Klick auf die Gruppenzeile auf- und zuklappen – dieser Zustand wird lokal gespeichert.

groupedBy: "", // default: 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) 

groupsCollapsed

Mit groupsCollapsed legst du fest, ob gruppierte Zeilen standardmäßig eingeklappt oder ausgeklappt dargestellt werden. Die Gruppenüberschrift (groupRow) ist dabei immer sichtbar – nur die zugehörigen Einträge (valueRows) werden bei Bedarf ein- oder ausgeblendet.

Dieser Parameter wirkt nur, wenn groupedBy gesetzt ist.

true = Gruppen sind beim Laden eingeklappt (kompakte Ansicht).
false = Gruppen sind beim Laden vollständig geöffnet.

Der Zustand (ein-/ausgeklappt) wird lokal gespeichert, d. h. bei erneutem Öffnen merkt sich das Widget den letzten Zustand pro Benutzer.

Standardwert: false (Gruppen sind offen) – wenn nicht angegeben, zeigt die Tabelle alle Gruppeneinträge vollständig an.

groupscollapsed: "", // default: false
groupsCollapsed: true,

🔸 embedded

Mit embedded aktivierst du den eingebetteten Modus der Tabelle. In diesem Modus passt sich die Tabelle optimal an bestehende Layoutstrukturen an – z. B. in einem Container, Tab oder einem flexiblen UI-Bereich.

Standardwert: false – die Tabelle nimmt dann ihren eigenen, festen Platz auf der Seite ein.

Wenn embedded: true gesetzt ist, wird das Widget nicht absolut, sondern relativ im Container positioniert und übernimmt dessen Breite und ggf. auch andere Stilvorgaben. Kombiniert mit Parametern wie height und minWidth sorgt das für ein sauberes, integriertes Erscheinungsbild.

Besonders nützlich ist embedded in Dashboards, Tab-Ansichten oder Modalfenstern.

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

🔸 rowHoverAction

Mit dem rowHoverAction-Block bestimmst du, ob das Hover-Verhalten auf Tabellenzeilen aktiv sein soll – und falls ja, welche Farben beim Überfahren mit der Maus verwendet werden.

  • hoverActive: true aktiviert den Effekt, andernfalls bleibt die Zeile beim Hover unverändert.

  • backgroundColor definiert die Hintergrundfarbe der Zeile im Hover-Zustand,

  • fontColor legt die Textfarbe während des Hoverns fest.

Standardwert bei hoverActive ist true, falls der Block gesetzt ist. Ohne rowHoverAction ist das Verhalten neutral – keine Hover-Effekte.

Tipp: Setze gedeckte Farben ein, um den Effekt dezent und UX-freundlich zu halten.

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

🔸 header

Mit dem header-Block steuerst du die Darstellung deiner Tabellenkopfzeile (Spaltenüberschriften). Du kannst sie ganz ausblenden, ihre Höhe anpassen sowie Farben und Schriftgrößen individuell gestalten.

  • showHeader (true/false): Blendet die gesamte Header-Zeile ein oder aus.

  • height: Legt die Höhe der Headerzeile in Pixeln fest – z. B. "48px" oder "auto".

  • fontColor: Definiert die Schriftfarbe der Spaltenüberschriften.

  • fontSize: Gibt die Schriftgröße an (z. B. "14px").

  • backgroundColor: Stellt den Hintergrund der Headerzeile ein – z. B. "white" oder ein Hexwert.

Standardverhalten:
Wenn showHeader nicht angegeben ist, wird die Header-Zeile angezeigt. Ohne weitere Einstellungen werden Standardwerte für Größe, Farbe und Hintergrund verwendet.

💡 Pro-Tipp:
Wenn du showHeader: false setzt, sollte die Bedeutung der Daten trotzdem klar erkennbar bleiben – z. B. durch die Position oder das Farbschema der Spalten. Ansonsten kann die Orientierung für Nutzer leiden.

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

🔸 emptyTable

Mit dem emptyTable-Block legst du fest, was angezeigt werden soll, wenn keine Daten vorhanden sind – also wenn data: [] leer ist. Du kannst Text und Gestaltung des leeren Zustands anpassen und so die Nutzererfahrung deutlich verbessern.

  • title: Der Haupttext, der angezeigt wird (meist prominent, z. B. „Keine Einträge gefunden“).

  • value: Optionaler zusätzlicher Text oder HTML-Elemente im Inneren des leeren Bereichs.

  • backgroundColor: Hintergrundfarbe für den leeren Bereich – z. B. "white" oder "#f4f6ff".

Standardverhalten:
Ohne emptyTable wird ein schlichter Text „Keine Ergebnisse“ angezeigt.

💡 Pro-Tipp:
Leere Zustände sind keine Fehler – sie sind deine Bühne. Nutze sie für Erklärungen, motivierende Hinweise oder einen klaren Call-to-Action („Jetzt neuen Eintrag erstellen“). So bleiben deine Nutzer nicht im Leeren hängen – im wahrsten Sinne.

emptyTable: {
			title: "", // Text der bei einer leeren Tabelle in einem abgerundeten Badge dargestellt wird.
            backgroundColor: "", // Hintergrundfarbe in HEX angeben
            value: "" // Hier kannst du eigene Widgets oder komplexe Ansichten einfügen, die den Title überschreiben.
		},

🔸 scrollBar

Mit dem scrollBar-Block konfigurierst du die horizontale Scrollbar deiner Tabelle. Diese wird angezeigt, wenn deine Tabelle mehr Spalten enthält, als in den verfügbaren Bereich passen.

  • showScrollBar: true oder false – bestimmt, ob die Scrollbar überhaupt angezeigt wird.

  • height: Höhe des Scrollbar-Containers (z. B. "10px").

  • backgroundColor: Hintergrundfarbe des Containers.

  • handle.height: Höhe des Schiebers („Handle“) innerhalb der Leiste.

  • handle.backgroundColor: Farbe des Scroll-Handles.

  • handle.borderRadius: Abgerundete Ecken des Schiebers (z. B. "5px" oder "50%").

Standardverhalten:
Ohne scrollBar wird keine sichtbare Scrollbar angezeigt – auch wenn Inhalte horizontal überlaufen.

💡 Pro-Tipp:
Gerade bei vielen Spalten hilft eine dezente, gut sichtbare Scrollbar, um Orientierung zu geben. Nutze weiche Farben und eine runde Handle-Form, damit die UI nicht „technisch“ wirkt – besonders auf Touch-Geräten zahlt sich das aus.

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

Mit dem theme-Parameter kannst du ein vordefiniertes Design-Template für deine Tabelle aktivieren. Das Theme beeinflusst das gesamte visuelle Erscheinungsbild – von Farben über Schriftarten bis hin zum Layout. Aktuell verfügbar sind:

  • "clean-white"

  • "naked"

Wichtig:
Damit das Theme korrekt greift, muss die theme-uniqueId die gleiche uniqueListId verwenden wie deine Tabelle. Nur so überschreibt das Theme gezielt die richtigen Style-Regeln per CSS.

Standardverhalten:
Wird kein theme gesetzt, wird das Standarddesign des arcCustomTable-Widgets verwendet (leicht schattiert, kontrastreich).

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

🔸 footer

Mit dem footer-Block kannst du einen unteren Bereich unterhalb der Tabelle anzeigen lassen – z. B. für Buttons oder Informationen. Er eignet sich ideal für Aktionsflächen wie „Neuen Eintrag anlegen“ oder zur Anzeige von Summen, Filtern oder Statusinfos.

  • showFooter: true oder false – aktiviert oder deaktiviert den Footer.

  • showActionButton: Zeigt den Standard-Button „Neuen Datensatz erstellen“ an.

  • actionButtonTitle: Individueller Text für den Action-Button.

  • backgroundColor: Hintergrundfarbe des Footers.

  • leftSideContent: Freier Inhalt (z. B. Text, HTML, Icons) für die linke Seite.

  • rightSideContent: Inhalt für die rechte Seite – z. B. Statusanzeigen, Summen oder Infos.

Standardverhalten:
Ohne footer-Block wird kein Footer angezeigt. Wird showFooter: true gesetzt, aber keine weiteren Optionen, erscheint ein leerer Footerbereich.

footer: {
			showFooter: true, 
			showActionButton: true,
            backgroundColor: "",
			actionButtonTitle: "Neue Aufgabe hinzufügen",
			leftSideContent: "", 
            rightSideContent: "Gesamt: " + cnt(filteredList) + " Aufgaben"
		}

So sieht der oben definierte Footer aus:

🔸 table

Im Detail-Bereich table definierst du alle Spalten (columns) und deren Darstellung, Inhalte und Verhalten. Du legst hier fest, welche Datenfelder angezeigt werden sollen, wie sie aussehen und was beim Klicken passieren soll.

  • Jede Spalte kann individuell formatiert werden (z. B. Farbe, Ausrichtung, Padding, Aktionen).

  • Die hier gesetzten Werte überschreiben ggf. globale Einstellungen aus dem settings-Block (z. B. fontColor, backgroundColor, align etc.).

  • Du kannst hier auch fixierte Spalten, Gruppierungen, Interaktionen und Inline-Editing steuern.

🔸 Zeilen- und Gruppenparameter

projectList.[{
				recordId: Nr,
				rowColor: "",
				rowHeight: "auto",
				rowPaddingY: "10px",
				groupRowColor: "",
                groupRowSettings: {
                    height: "",
                },
  • recordId:
    Muss die Nr des Datensatzes sein (also die interne ID in Ninox).
    Wichtig für die Zuordnung von Aktionen, z. B. Öffnen, Bearbeiten, Löschen.

  • rowColor:
    Setzt die Hintergrundfarbe der jeweiligen Zeile.
    Akzeptiert HEX-Werte wie "#f4f6ff" oder "transparent".

  • rowHeight:
    Bestimmt die Höhe der Zeile.
    Wert kann "auto" sein oder eine feste Pixelangabe wie "60px".

  • rowPaddingY
    → Vertikales Innenabstands-Polster (top/bottom) innerhalb der Zellen dieser Zeile.
    Wird auf alle Zellen angewendet, sofern dort kein individuelles Padding gesetzt ist.

  • groupRowColor:
    Setzt die Hintergrundfarbe für eine Gruppen-Zeile (wenn groupedBy aktiv ist).
    Du kannst entweder HEX-Werte verwenden oder dynamisch auf Felder zugreifen (z. B. row.farbe).

  • groupRowSettings.height
    → Legt die Höhe der Gruppenzeile fest.
    Wert z. B. "40px" oder "auto". Wirkt nur, wenn die Zeile eine Gruppenzeile ist.

💡 Pro-Tipp:
Du kannst dynamisch berechnete Farben einsetzen, um Status-Feedback direkt sichtbar zu machen – z. B. grün für „alle erledigt“, grau für „in Arbeit“:

groupRowColor: if cnt(Firma.Projekte) = cnt(Firma.Projekte[Abgeschlossen != null]) then
					"#F0FFF1"
				else
					"#eee"
				end,

🔸 columns

Im columns-Array definierst du die einzelnen Spalten deiner Tabelle – also wie sie aussehen, heißen und was darin angezeigt wird. Jede Spalte wird über ein eigenes Objekt innerhalb von columns beschrieben.

Basics, die du einstellen kannst:

  • field: Das Datenfeld, das angezeigt werden soll – muss zu den Werten in data.table.columns passen.

  • title: Der sichtbare Name der Spalte im Header.

  • width: Die Breite der Spalte (z. B. "200px").

  • align: Ausrichtung des Inhalts – "left", "center" oder "right".

  • backgroundColor / color: Hintergrund- und Textfarbe der Spalte.

  • paddingX / paddingY: Innenabstände horizontal und vertikal.

  • truncate: Ob der Text abgeschnitten und mit „…“ versehen werden soll.

  • fixed: "left" oder "right", um eine Spalte zu fixieren.

  • actions: Aktionen wie update, popup, change, openFullscreen, delete.

columns: [{
    			field: "", 
                title: "", 
                value: "", 
                width: "", 
                align: "", 
                fixed: "", 
                paddingX: "",
                paddingY: "", 
                groupExpandAction: "",
                groupValue: "",
                actions: [{
                    recordId: "", 
                    type: "", 
                    field: "", 
                    value: ""
                }]        
		}

Gruppen ausklappen mit groupExpandAction

Mit groupExpandAction kannst du bestimmen, bei welchen Spalten die Funktion des Ausklappens aktiviert sein soll. Das funktioniert nur, wenn du eine Gruppierung in deiner Tabelle eingestellt hast. Aktivierst du es bei mindestens einer Spalte (mit groupExpandAction:true), ist es bei den anderen Spalten automatisch deaktiviert, sofern du es dort nicht auch mit aktivierst in den Parametern.

groupExpandAction: true, // Aktiviert das Ausklappen der Tabellenzeilen durch Klick auf die Spalte.
groupExpandAction: false, // Deaktiviert das Ausklappen der Tabellenzeilen durch Klick auf die Spalte.
groupExpandAction: "", // default: true

🔸 actions

Mit dem Parameter actions kannst du festlegen, was passieren soll, wenn ein Nutzer auf eine Zelle klickt oder diese bearbeitet. Aktionen werden auf Zellebene innerhalb von columns (in data.table) gesetzt und machen deine Tabelle interaktiv.

💡 Hinweis: Du kannst mehrere Aktionen kombinieren, indem du sie als Array einfügst.
Beispiel:

actions: [{
	recordId: Nr,
	type: "popup"
	}, {
	recordId: Nr,
	type: "change",
	field: "A"
}],

🔸 Aktion: popup

Mit type: "popup" definierst du eine Aktion, die beim Klick auf die Zelle den verknüpften Datensatz als Popup öffnet – direkt innerhalb von Ninox. Dadurch können Nutzer Details einsehen oder bearbeiten, ohne die aktuelle Ansicht zu verlassen.

  • recordId muss die Nr des jeweiligen Datensatzes sein.

  • Diese Aktion gilt immer für die ganze Zelle, nicht nur für den Text.

  • Du kannst mit showPopupButton: true zusätzlich einen Button anzeigen lassen, der den Popup explizit auslöst – nützlich, wenn du Editieren und Öffnen visuell trennen möchtest.

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: ""
	})
}]

Statt die gesamte Zelle klickbar zu machen, kannst du auch einen individuellen Button innerhalb der Zelle anzeigen lassen – z. B. mit dem Widget arcCustomButton.

Dazu verwendest du:

  • showPopupButton: true – aktiviert die Schaltfläche.

  • popupButton – enthält das gerenderte Button-Element, z. B. per arcCustomButton().

🔸 Aktion: delete

Mit type: "delete" kannst du beim Klick auf eine Zelle den zugehörigen Datensatz löschen. Die Aktion wirkt sich – wie bei popupauf die gesamte Zelle aus.

  • recordId muss auf die Nr des Datensatzes zeigen, der gelöscht werden soll.

  • Es wird kein zusätzlicher Bestätigungsdialog eingebaut – das Löschen erfolgt direkt.

💡 Hinweis: Diese Aktion sollte nur mit Bedacht und klar visualisiert eingesetzt werden – z. B. durch eine spezielle Icon-Spalte oder einen rot markierten Button innerhalb der Zelle.

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

🔸 Aktion: update

Mit type: "update" kannst du beim Klick auf eine Zelle direkt ein Feld des verknüpften Datensatzes ändern – ohne Popup, ohne Edit-Modus.

  • recordId: Die Nr des Datensatzes, der verändert werden soll.

  • field: Das Feld, das aktualisiert wird (als Text).

  • value: Der neue Wert, der gesetzt werden soll (Text, Zahl, Bool, etc.).

actions: [{
  recordId: Nr,
  type: "update",
  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. 
}]

💡 Pro-Tipp:
Wenn du das Löschen nicht direkt, sondern erst nach einer Sicherheitsabfrage durchführen möchtest, kannst du einen kleinen Umweg über ein Hilfsfeld + Trigger nehmen:

  1. Erzeuge ein Ja/Nein-Feld namens z. B. trigger_delete.

  2. Füge in der Tabelle eine update-Aktion ein, die trigger_delete auf true setzt.

  3. Im Trigger dieses Feldes nutzt du folgenden Dialog:

if dialog("Eintrag Löschen", "Soll der Eintrag wirklich gelöscht werden?", ["Ja, löschen!", "Abbrechen"]) = "Ja, löschen!" then
	delete this
end;
trigger_delete := false

🔸 Aktion: openFullscreen

Mit type: "openFullscreen" öffnest du den verknüpften Datensatz direkt im Vollbildmodus – also so, als würde man ihn klassisch in Ninox vollständig aufrufen.

  • recordId: Die Nr des Datensatzes, der geöffnet werden soll.

Einsatzszenario:
Wenn du komplexe Datensätze mit vielen Tabs oder Untertabellen hast, ist openFullscreen die bessere Wahl gegenüber popup.

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

🔸 groupValue

Mit groupValue definierst du den Inhalt der Gruppierungszeile in einer bestimmten Spalte – also das, was in der Zeile angezeigt wird, die z. B. mehrere Datensätze zu einem Projekt, Kunden oder Status bündelt.

  • Du kannst groupValue in jeder Spalte verwenden – auch mehrfach pro Gruppe, wenn gewünscht.

  • Du kannst einfachen Text, HTML oder auch Mini-Widgets einbauen (z. B. Buttons, Layouts oder Statusanzeigen).

  • Die Gruppierungszeile wird automatisch angezeigt, wenn groupedBy im settings-Block gesetzt ist.

groupValue: Projekte.Bezeichnung // Ninox-Felder & -Schreibweisen möglich
groupValue: "Projekt:" + Projekte.Bezeichnung // Text + Ninox-Feld
groupValue: arcCustomProgressBar({
        uniqueId: "",
        width: "",
        fontSize: "",
        fontColor: "",
        backgroundColor: "",
        progressColor: "",
        valueTotal: "",
        valueProgress: "",
        valueText: ""
    }) // Andere Mini-Widgets

🔸 groupByValue

Der groupByValue-Parameter erlaubt es, deine Tabelle nach einem anderen Wert als dem angezeigten value zu gruppieren. So kannst du die Anzeige der Zelle unabhängig von der Logik der Gruppierung steuern.

  • value: Was der Nutzer in der Zelle sieht (z. B. ein Icon, ein Label, ein HTML-Element).

  • groupByValue: Nach diesem Wert wird die Zeile gruppiert.

Fallback:
Wenn value oder groupByValue leer ist, wird die Zeile automatisch der Gruppe arc-no-value zugeordnet.
Diese Gruppe wird ganz normal dargestellt, kann aber auch gezielt angesprochen oder ausgeblendet werden.


groupByValue: Projekte.Nr // 
groupByValue: Typ // Ninox-Felder
groupByValue: "" // default: es wird nach value gruppiert

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)),
		height: "auto",
		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({
								uniqueId: "checkbox all check",
								value: Erledigt,
								embedded: true,
								clickAction: {
									recordId: Nr,
									fieldId: "G",
									value: 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({
								uniqueId: "checkbox single check",
								value: Erledigt,
								embedded: true,
								clickAction: {
									recordId: Nr,
									fieldId: "G",
									value: if Erledigt = true then null else true end
								}
							}),
						width: "100px",
						align: "center",
						fixed: "left",
						groupValue: arcCustomIcon({
								name: "caret-down"
							})
					}, {
						field: "Bild",
						title: "Logo",
						width: "150px",
						value:"",
						actions: [{
								recordId: Projekte.Nr,
								type: "popup"
							}],
						groupValue: "",
					}, {
						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:"",
						actions: [{
								recordId: Mitarbeiter.Nr,
								type: "popup"
							}]
					}, {
						field: "delete",
						title: "",
						width: "40px",
						align: "center",
						value: "",
						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

Arc Rider Ventures GmbH

© 2025

Arc Rider Ventures GmbH

© 2025