Module (NXM)
Ansichten und das View-SDK
Wie ein NXM-Modul seine Datensätze zeigt. Deklarative Ansichten, die nexxus für Sie zeichnet, eigene HTML-Ansichten in einer Sandbox und das View-SDK, das beide mit der Plattform verbindet.
Ein NXM-Modul hat zwei Wege, etwas auf den Bildschirm zu bringen. Die meisten Seiten brauchen gar keinen Code: Sie beschreiben eine Liste oder eine Datensatzseite in der module.json, und nexxus zeichnet sie mit denselben Bausteinen wie seine eingebauten Module. Braucht eine Seite ein eigenes Layout, etwa einen Kalender, ein Cockpit aus mehreren Blöcken oder ein PDF mit Notizen daneben, schreiben Sie eine HTML-Datei. nexxus führt diese Datei in einem abgeschotteten Rahmen aus und gibt ihr eine kleine JavaScript-Schnittstelle mit, das View-SDK (window.nx).
Diese Seite behandelt beides. Fangen Sie mit den deklarativen Ansichten an und greifen Sie erst dort zu einer eigenen Ansicht, wo diese nicht mehr reichen.
Zwei Arten von Ansichten
Abschnitt betitelt „Zwei Arten von Ansichten“| Deklarative Ansichten | Eigene Ansichten | |
|---|---|---|
| Geschrieben als | JSON in der module.json (type: list, record, related) | Eine HTML-Datei je Ansicht (type: "custom", html: "ui/<name>.html") |
| Gezeichnet von | nexxus selbst | Ihrem HTML, in einem abgeschotteten Rahmen |
| Sieht aus wie | der Rest von nexxus, ganz von selbst | nexxus, wenn Sie das UI-Kit und die Farb-Tokens verwenden |
| Datenzugriff | eingebaut: Listen, Filter, Formulare, Bezugslisten | über window.nx, als die Person, die die Ansicht betrachtet |
| Gut für | Listen, Datensatzformulare, Listen verknüpfter Datensätze | Seiten, Cockpits, Kalender, Dialoge, PDF-Prüfung |
Beide Arten handeln mit den Rechten der Person auf der Seite. Eine eigene Ansicht bekommt nie mehr Zugriff als die Person, die sie geöffnet hat, und der Server prüft jeden ihrer Aufrufe noch einmal.
Ihre Ansicht
Eine HTML-Datei mit eingebettetem Skript und Stil, in einem abgeschotteten Rahmen.
Das View-SDK
window.nx schickt jede Anfrage über einen eigenen Nachrichtenkanal.
Der Host in nexxus
Ergänzt Modul und Sitzung, zeigt Meldungen, Dialoge und den PDF-Viewer.
Die Plattform-API
Prüft die Rechte der betrachtenden Person und antwortet.
Deklarative Ansichten
Abschnitt betitelt „Deklarative Ansichten“Diese vier Typen brauchen kein HTML. nexxus baut daraus Listen, Formulare, Reiter und Karten.
list: die Listenseite eines Fachobjekts unter/x/<modul>/<fachobjekt>. Sie wählen diecolumns(einen Feldschlüssel oder{ "field": "status", "display": "badge" }), diefiltersund eine Standardsortierungsort;"create": truezeigt die Schaltfläche für einen neuen Datensatz. Filtern und sortieren lässt sich nur nach indizierten Feldern. Fehlt eine Listenansicht, baut nexxus sie aus demtitleFieldund den ersten vier indizierten Feldern. Die Liste zeigt jeden Datensatz als Zeile im Listenstil von nexxus, und jede Spalte bleibt sichtbar: DastitleFieldwird die Überschrift, Verweise und Textfelder stehen darunter, die erste Person (core:user) mit ihrer Bezeichnung daneben. Auswahlfelder, Daten und Zahlen stehen rechts, der erste Betrag hervorgehoben, und die Badge-Spaltestatus(sonst die erste Badge-Spalte) als Chip. Unter Ansichtsoptionen wählt jede Person die Dichte Normal oder Kompakt und speichert eigene Ansichten.record: der Reiter Daten eines Datensatzes.sectionsgliedern die Felder,relatedfügt Listen der Datensätze hinzu, die auf diesen verweisen, undactionslegt fest, welche Aktionen die Aktionsleiste anbietet.related: ein Reiter auf der Seite eines anderen Fachobjekts, der die Datensätze auflistet, die darauf verweisen. Bei Kerndaten ist das die Seite eines Partners, Projekts, einer Rechnung oder einer Opportunity ("target": "core:partner","core:project","core:invoice"oder"core:opportunity", Slotrecord.tab).map: die Datensätze eines Fachobjekts auf einer Karte, zusammen mit ihrer Liste, als Seite des Moduls unter/x/<modul>/p/<ansicht>.geoFieldnennt dasgeo-Feld, das einen Datensatz auf die Karte setzt.
Die vollständige Feldreferenz dieser Ansichten steht unter Paketaufbau.
So ist eine Datensatzseite aufgebaut
Abschnitt betitelt „So ist eine Datensatzseite aufgebaut“Die Datensatzseite eines Paket-Fachobjekts zeigt ihre Reiter in dieser Reihenfolge:
- alle Ansichten mit Slot
record.detail(eigene Ansichten zu diesem Datensatz), - den Reiter Daten (die
record-Ansicht oder, falls es keine gibt, alle Felder), - alle Ansichten des Moduls mit Slot
record.tab, - die Bezugslisten.
Dort erscheinen nur Ansichten des eigenen Pakets: Pakete bauen nicht aufeinander auf, also bringt kein anderes Paket Reiter oder Dialoge auf die Seite. Aktionen stehen in der Aktionsleiste unten im Reiter.

Slots: wo eine eigene Ansicht erscheint
Abschnitt betitelt „Slots: wo eine eigene Ansicht erscheint“Eine eigene Ansicht nennt einen slot. Er bestimmt, wo nexxus sie zeigt und welchen Kontext sie bekommt.
| Slot | Im Katalog angezeigt als | Wo sie erscheint | target |
|---|---|---|---|
page | Seite | Eine eigene Seite unter /x/<modul>/p/<ansicht>. Sie füllt den Bereich und kann ein Menüeintrag sein. | keins |
record.detail | Ansicht am Datensatz | Die ersten Reiter einer Datensatzseite | ein Fachobjekt des Pakets |
record.tab | Reiter am Datensatz | Ein Reiter nach Daten; mit einem Kernziel ein Reiter auf der Partner-, Projekt-, Rechnungs- oder Opportunity-Seite | ein Fachobjekt oder core:partner, core:project, core:invoice, core:opportunity |
record.action | Dialog am Datensatz | Ein Dialog, den die Aktionsleiste des Datensatzes öffnet | ein Fachobjekt |
dashboard.widget | Kachel auf dem Dashboard | Eine Kachel mit size s, m oder l | keins |
member | Seite im Kundenbereich | Eine Seite des Kundenbereichs auf der Portal-Domain, unter /konto/<ansicht>, fensterfüllend | keins |
Über einer Seite und einer Ansicht am Datensatz zeigt nexxus den Titel: auf einer Seite die Beschriftung der Ansicht, auf einem Datensatz dessen Titel. Die Ansicht wiederholt ihn nicht und beginnt mit dem, was sie ergänzt, etwa einem Zeitraum, einer Anzahl oder Filtern. Auch Kachel und Dialog bekommen ihre Titelleiste von nexxus.
Auf die Startseite kommt eine Kachel auf zwei Wegen: Eine Person legt sie mit Anpassen und Widget hinzufügen an, wo Beschriftung, Symbol und Modulname der Ansicht stehen, oder sie wendet eine Vorlage des Pakets an (siehe Startseiten-Vorlagen). Von selbst erscheint keine. Ist das Modul deaktiviert oder entfernt, zeigt eine platzierte Kachel Modul nicht verfügbar und kommt mit dem Modul zurück.
{ "key": "faellig", "type": "custom", "slot": "page", "html": "ui/faellig.html", "label": { "de": "Fällige Rückgaben", "en": "Due returns" } }Eine Ansicht nur zeigen, wenn sie passt
Abschnitt betitelt „Eine Ansicht nur zeigen, wenn sie passt“Ansichten und Aktionen nehmen eine optionale Bedingung when. nexxus blendet die Ansicht aus, wenn die Bedingung für den aktuellen Datensatz nicht gilt, und der Server prüft sie vor jeder Aktion erneut.
"when": { "field": "status", "in": ["verfuegbar"] }"when": { "field": "dokument", "set": true }in gilt, wenn der Wert des Felds einer der genannten ist (bei einem Listenfeld, wenn es irgendein Element ist). set: true gilt, wenn das Feld einen Wert hat, set: false, wenn es leer ist.
Die Sandbox
Abschnitt betitelt „Die Sandbox“Jede eigene Ansicht läuft in einem <iframe> mit sandbox="allow-scripts allow-forms" ohne eigenen Ursprung und unter derselben Inhaltsrichtlinie wie Apps:
default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline';img-src data: blob:; font-src data:; media-src data: blob:; form-action 'none'; base-uri 'none'Die Sandbox gibt es, weil der Code eines Pakets nicht von nexxus stammt. Was die Ansicht auch tut, sie erreicht kein Netzwerk, liest keine Sitzung und berührt nicht die Seite um sie herum. Im Alltag heißt das:
- Alles eingebettet. Skripte, Stile, Schriften und Bilder stehen in der Datei oder als
data:- bzw.blob:-URL.fetch, XHR, WebSockets und<script src>aus dem Netz sind gesperrt. - Keine Cookies, kein
localStorage. Der Rahmen hat keinen Ursprung. Was eine Person wiederfinden soll, legen Sie mitnx.storageab. - Formulare ja, Absenden nein. Ein
<form>löst seinsubmit-Ereignis aus, aberform-action 'none'sperrt alles, was die Seite verlassen würde. Rufen SiepreventDefault()auf und verarbeiten Sie die Daten selbst. - Keine Pop-ups, keine Downloads.
- Keine Symbolschrift. Die Schrift Material Symbols von nexxus steht im Rahmen nicht zur Verfügung. Verwenden Sie eingebettetes SVG.
- Text als Text. Datensätze enthalten, was Menschen eingetippt haben. Setzen Sie solche Werte mit
textContentein, nie mitinnerHTML.
SDK und UI-Kit werden vor Ihrem eigenen Code eingefügt, window.nx steht also bereit, wenn Ihr erstes Skript läuft. Eine HTML-Datei darf bis zu 2 MB groß sein.
Eine minimale Ansicht
Abschnitt betitelt „Eine minimale Ansicht“Diese Seite listet die verliehenen Geräte aus dem Tutorial zum ersten Modul:
<!doctype html><html><head> <meta charset="utf-8"> <style>body { padding: 16px; }</style></head><body> <div class="nx-list" id="list"></div> <script> (async () => { const ctx = await nx.ready(); const {items} = await nx.records.search('geraet', { filter: {status: ['verliehen']}, sort: 'rueckgabe_am', size: 50, }); for (const geraet of items) { const item = document.createElement('button'); item.className = 'nx-list__item'; item.textContent = geraet.title; item.onclick = () => nx.nav.open({entity: 'geraet', id: geraet.id}); document.getElementById('list').append(item); } })(); </script></body></html>Kontext und Ereignisse
Abschnitt betitelt „Kontext und Ereignisse“await nx.ready() kehrt zurück, sobald der Host verbunden ist, und liefert den Kontext der Ansicht:
| Feld | Bedeutung |
|---|---|
sdk | Protokollversion, derzeit 1 |
module, version, view, slot | Wo die Ansicht läuft |
locale | de, en oder pl, die Sprache der Person |
theme | light oder dark |
user | {id, name} der Person, die die Ansicht betrachtet |
record | {entity, id} auf der Datensatzseite eines Fachobjekts aus dem Paket der Ansicht, z. B. {entity: 'akte', id: 12} |
target | {type, id} auf einem Kerndatensatz, z. B. {type: 'core:project', id: 7} |
params | Was der Aufrufer mitgegeben hat |
nx.on(name, fn) meldet einen Empfänger für ein Ereignis an und gibt eine Funktion zurück, die ihn wieder abmeldet.
context: Der Kontext hat sich geändert (ein anderer Datensatz, eine andere Sprache). Das Argument ist der neue Kontext.theme: Hell oder dunkel hat gewechselt, als{theme, tokens}. Das SDK hat den Wechsel schon übernommen. Hören Sie nur zu, wenn Sie selbst zeichnen, etwa auf einem Canvas oder in einem Diagramm.record: nexxus hat den Datensatz, um den es in Ihrer Ansicht geht, außerhalb der Ansicht geändert, als{entity, id, version}. Das passiert, nachdem eine Aktion darauf lief, ein Dialog ihn geschrieben hat, der Reiter Daten gespeichert wurde oder eine andere Ansicht ihn geändert hat. Bei Kerndatensätzen istversionnull. Ihre eigenen Schreibvorgänge kommen nicht als Ereignis zurück.
Das Ereignis sagt, dass sich etwas geändert hat, nicht was. Lesen Sie den Datensatz neu:
const ctx = await nx.ready();let shown = await nx.records.get(ctx.record.entity, ctx.record.id);render(shown);
nx.on('record', async ({version}) => { if (version !== null && version === shown.version) return; shown = await nx.records.get(ctx.record.entity, ctx.record.id); render(shown);});Änderungen, die nexxus nicht in diesem Browser-Tab vorgenommen hat, etwa von einer anderen Person oder von einem Moduldienst im Hintergrund, werden nicht gemeldet.
SDK-Referenz
Abschnitt betitelt „SDK-Referenz“Jeder Aufruf gibt ein Promise zurück. Ein fehlgeschlagener Aufruf wird mit einem nx.NxError abgelehnt, der code, message und bei Prüffehlern fieldErrors trägt. Lehnt ein Moduldienst eine Aktion ab, ist code SERVICE_REJECTED, serviceCode der eigene Code des Dienstes (etwa COMPOSE_STALE) und serviceStatus sein HTTP-Status; prüfen Sie serviceCode, nicht den Text, der in der Sprache der Person steht.
| Aufruf | Ergebnis |
|---|---|
nx.ready() | Der Kontext (siehe oben) |
nx.on(name, fn) | Meldet einen Empfänger für context, theme oder record an; gibt eine Abmeldefunktion zurück |
nx.records.search(entity, {q?, filter?, sort?, from?, size?}) | {items, total}. filter je Feld: ein Wert, eine Liste von Werten oder {from, to}. sort: 'feld', 'feld,asc' oder 'feld,desc' (siehe unten). size höchstens 200 |
nx.records.get(entity, id) | Der Datensatz |
nx.records.create(entity, data) | Der neue Datensatz |
nx.records.update(entity, id, patch, {version?}) | Der Datensatz. Mit version schlägt der Aufruf mit CONFLICT fehl, wenn auf dem Server ein neuerer Stand liegt |
nx.records.remove(entity, id) | true |
nx.lookup(target, {q?, ids?}) | [{id, label, sublabel}]. Ziele: ein Fachobjekt des Moduls, 'core:partner', 'core:partnerContact', 'core:project', 'core:invoice', 'core:opportunity', 'core:user', 'core:dmsDocument', 'core:ismsMeasure'. Ohne q die ersten 20 |
nx.invoke(action, {recordId?, payload?}) | {result, record?}. Führt eine Aktion des Moduls aus; der Server prüft ihr Recht und ihr when. Eine Aktion, die eine E-Mail versendet, fragt die Person vorher, siehe unten |
nx.actions.preview(action, recordId) | {recipient: {name, address}, subject, text, fileName}: was eine Aktion, die eine E-Mail versendet, für den Datensatz versenden würde. Versendet nichts |
nx.nav.open(target) | Öffnet {entity, id}, {list: entity}, {view} (eine Seite des Moduls) oder {core, id} mit core gleich 'partner', 'project', 'invoice' oder 'opportunity'. {view, id} mit einer record.action-Ansicht öffnet deren Dialog für diesen Datensatz und liefert, was der Dialog an nx.dialog.close() übergeben hat, oder null, wenn er abgebrochen wurde. {view, id} mit einer map-Ansicht öffnet die Karte auf diesem Datensatz (?focus=<id>) |
nx.ui.toast(message, {kind?}) | Zeigt eine Meldung; kind ist success, error oder info |
nx.ui.confirm({title, message, confirmLabel?, danger?}) | true, wenn bestätigt. nexxus zeigt dafür seinen eigenen Dialog |
nx.dialog.close(result?) | Nur in record.action-Ansichten: schließt den Dialog und gibt result an den Aufrufer |
nx.storage.get(key) | Der gespeicherte Wert, je Person und Ansicht |
nx.storage.set(key, value) | Speichert einen Wert im Profil der Person, er folgt ihr also auf andere Geräte. set(key, null) entfernt ihn |
nx.assistant.setContext({summary, records?}) | Sagt dem KI-Assistenten, was die Ansicht zeigt. records ist [{entity, id}]; ein leeres Objekt zieht den Kontext zurück |
nx.assistant.ask(prompt) | Öffnet die Assistentenspalte und stellt prompt als neues Gespräch |
nx.t({de, en, pl}) | Der Text in der Sprache der Person, sonst der englische, sonst der deutsche. pl ist optional |
nx.pdf.mount(element, {documentId, page?, highlights?}) | Ein Handle für einen PDF-Viewer über element (siehe unten) |
nx.images.url(documentId, {width?}) | Eine blob:-Adresse für das Bild des Dokuments, für <img src>. nexxus lädt die Datei mit den Leserechten der Person, die die Ansicht ansieht, und nimmt nur Bilder bis 15 MB an. Mit width, der Breite auf dem Bildschirm in CSS-Pixeln, kommt eine passend verkleinerte Kopie statt des Originals, und der Browser behält sie zehn Minuten. Dieselbe ID und Breite gibt dieselbe Adresse und wird einmal geladen; höchstens vier laden gleichzeitig |
nx.files.upload(file, {entity, field, name?}) | {id, documentId, name, type, size, url}. Legt eine Datei aus dem eigenen Eingabefeld der Ansicht, aus einem Ablegen oder von der Kamera als Dokument der Person ab, für ein Feld von entity, das auf Dokumente verweist. documentId schreibt die Ansicht selbst in dieses Feld; url zeigt die Datei sofort. In Ansichten der Slots record.detail, record.tab und page, mit dem Scope core:dmsDocument:create, siehe Fotos und Dateien aus der Ansicht |
Fachobjekte sind die des eigenen Pakets, genannt mit ihrem Schlüssel ('geraet'). Eine Ansicht erreicht kein anderes Paket: Ein Name mit einem Paketschlüssel davor, etwa 'curiaos.kanzlei:akte', scheitert mit INVALID_PARAMS. Suchen filtern nur nach indizierten Feldern.
sort nimmt ein indiziertes Feld oder eines von id, createdAt (angelegt) und updatedAt (zuletzt geändert). Ohne Richtung sortiert es aufsteigend. Ohne sort kommt der zuletzt angelegte Datensatz zuerst. Datensätze ohne Wert im Sortierfeld stehen am Ende, bei gleichem Wert steht der zuletzt angelegte vorn. nx.records.search('geraet', {sort: 'updatedAt,desc', size: 10}) liefert die zehn zuletzt geänderten Datensätze.
Aktionen, die eine E-Mail versenden
Abschnitt betitelt „Aktionen, die eine E-Mail versenden“Eine Aktion vom Typ mail lässt nexxus im Namen Ihrer Organisation eine E-Mail mit einem PDF an die Adresse eines Kontakts versenden. Die Adresse nimmt nexxus aus dem Kontakt selbst, nie aus Ihrer Ansicht, und fragt die Person, bevor etwas hinausgeht.
Ruft Ihre Ansicht nx.invoke für eine solche Aktion auf, öffnet nexxus außerhalb Ihres Rahmens seinen eigenen Dialog E-Mail versenden. Er zeigt den confirm-Text der Aktion, dann An mit Name und Adresse des Empfängers, Betreff, den Text der E-Mail und Anhang mit dem Dateinamen des PDFs, alles so, wie der Server es ermittelt hat. Nur Versenden versendet, und zwar genau das, was der Dialog gezeigt hat. Abbrechen, das Schließen-Symbol oder Escape lehnen Ihren Aufruf mit CANCELLED ab. Derselbe Dialog öffnet sich, wenn jemand die Aktion in der Aktionsleiste des Datensatzes anklickt.
- Fragen Sie nicht vorher mit
nx.ui.confirm. Die Person müsste sonst zweimal bestätigen. - Hat der Kontakt keine E-Mail-Adresse, zeigt der Dialog die Meldung des Servers und bietet nur Schließen an. Ihr Aufruf scheitert dann mit
CANCELLED,nx.actions.previewmitNO_ADDRESS. - Haben sich der Datensatz oder der Empfänger zwischen Vorschau und Versand geändert, scheitert der Aufruf mit
CONFIRMATION_STALE. Rufen Sienx.invokeerneut auf, dann kommt eine frische Vorschau. nx.actions.preview(action, recordId)liefert dieselbe Vorschau, damit Ihre Ansicht sie neben ihrem Knopf zeigen kann. Sie enthält nie das Token, das einen Versand an die Vorschau bindet. Eine Ansicht kann den Dialog also nicht umgehen.
const mail = await nx.actions.preview('entwurf-versenden', ctx.record.id);showPreview(mail.recipient.name, mail.recipient.address, mail.subject, mail.text, mail.fileName);
try { await nx.invoke('entwurf-versenden', {recordId: ctx.record.id});} catch (e) { if (e.code !== 'CANCELLED') nx.ui.toast(e.message, {kind: 'error'});}Fotos und Dateien aus der Ansicht
Abschnitt betitelt „Fotos und Dateien aus der Ansicht“Eine Ansicht auf einer Datensatzseite oder auf einer eigenen Seite kann Fotos und andere Dateien aufnehmen, etwa auf einem Tablet vor Ort. Das <input type="file"> bleibt das der Ansicht. nexxus legt die Datei unter Dateien als Dokument der Person ab und gibt ihre ID zurück, die die Ansicht in ein Feld schreibt, das auf Dokumente verweist.
- Tragen Sie den Scope
core:dmsDocument:createunterscopesein. Die Administration stimmt ihm beim Installieren des Pakets zu (Dokumente anlegen). Ohne ihn scheitert der Aufruf mitCONSENT_REQUIRED. - Geben Sie der Entität ein
ref-Feld mit"target": "core:dmsDocument", mit"multiple": truefür mehrere Dateien und"accept": ["image/*"], wenn dort nur Bilder hingehören. - Rufen Sie
nx.files.upload(file, {entity, field})auf und speichern Sie die zurückgegebenedocumentIdim Feld.
// <input type="file" id="photo" accept="image/*" capture="environment">const input = document.querySelector('#photo');input.addEventListener('change', async () => { const file = input.files[0]; if (!file) return; try { const photo = await nx.files.upload(file, {entity: 'component', field: 'photos'}); preview.src = photo.url; const record = await nx.records.get('component', ctx.record.id); const photos = [...(record.data.photos || []), photo.documentId]; await nx.records.update('component', record.id, {photos}, {version: record.version}); } catch (e) { nx.ui.toast(e.message, {kind: 'error'}); }});- Was nexxus prüft: Die Person darf Datensätze der Entität ändern, das Feld verweist auf Dokumente und sein
acceptnimmt die Datei, die Datei ist ein Dokument, Bild, Office-Datei oder eine E-Mail, und sie ist höchstens 25 MB groß. Eine größere Datei weist nexxus ab, bevor sie gesendet wird (TOO_LARGE). - Wo die Datei landet: in einem Ordner mit dem Namen des Pakets in den eigenen Dateien der Person, angelegt beim ersten Hochladen. Einzurichten ist nichts, denn wer einen Datensatz lesen darf, der auf die Datei verweist, darf auch die Datei lesen.
- Wahlweise ein Ordner fürs Team: Die Administration legt unter Dateien einen obersten Ordner mit dem Namen des Pakets in der Sprache der Organisation an und gibt ihn mit dem Recht zum Bearbeiten frei. Die Dateien aller, die ihn sehen und keinen eigenen Ordner dieses Namens haben, landen dann dort. Ist er nur zum Lesen freigegeben, scheitert ihr Hochladen.
- Wer sie sieht: die Person, die sie hochgeladen hat, alle, für die der Ordner freigegeben ist, und alle, die einen Datensatz des Pakets lesen dürfen, der auf die Datei verweist.
- Das Hochladen allein ändert keinen Datensatz. Eine Datei, die nie in ein Feld kommt, bleibt in den Dateien der Person.
- HEIC: iPads und iPhones geben einem Dateifeld meist ein JPEG. Eine HEIC-Datei wird so abgelegt, wie sie ist, und außer Safari zeigt sie kein Browser an.
- Nicht verfügbar in Kacheln der Startseite, in Aktionsdialogen (
record.action) und in öffentlichen Formularen: Dort scheitert der Aufruf mitNOT_AVAILABLE.
Später zeigt die Ansicht ein abgelegtes Foto mit nx.images.url(documentId).
Fehlercodes
Abschnitt betitelt „Fehlercodes“| Code | Stammt von | Bedeutung |
|---|---|---|
VALIDATION | Server | Die Daten wurden abgelehnt; fieldErrors nennt die Felder |
FORBIDDEN | Server | Der Person fehlt das Recht |
NOT_FOUND | Server | Datensatz, Aktion oder Ansicht gibt es nicht |
MODULE_INACTIVE | Server | Das Modul ist deaktiviert |
CONFLICT | Server | Jemand hat den Datensatz geändert, seit Sie ihn gelesen haben |
UNIQUE | Server | Ein eindeutiger Wert ist schon vergeben |
NO_ADDRESS | Server | Der Kontakt einer Aktion, die eine E-Mail versendet, hat keine E-Mail-Adresse |
CONFIRMATION_STALE | Server | Datensatz oder Empfänger haben sich geändert, seit die Vorschau der E-Mail gezeigt wurde, oder die Vorschau ist abgelaufen |
CONSENT_REQUIRED | Server | Dem Paket fehlt der Scope, den der Aufruf braucht, etwa core:dmsDocument:create für nx.files.upload |
INVALID_PARAMS | Host | Ein Parameter hatte die falsche Form; die Meldung nennt ihn |
UNKNOWN_METHOD | Host | Diese SDK-Methode gibt es nicht |
BUSY | Host | Zu viele Aufrufe gleichzeitig, oder eine Bestätigung ist schon offen |
CANCELLED | Host | Die Person hat den Dialog einer Aktion, die eine E-Mail versendet, geschlossen, ohne zu versenden |
STORAGE_FULL | Host | Das Speicherlimit dieser Ansicht ist erreicht |
NOT_IN_DIALOG | Host | nx.dialog.close() außerhalb einer record.action-Ansicht |
NO_USER_ACTION | Host | Der Aufruf braucht zuerst einen Klick oder Tastendruck in der Ansicht |
NOT_AVAILABLE | Host | Den Aufruf gibt es in dieser Art von Ansicht nicht, etwa nx.files.upload in einer Kachel |
NOT_AN_IMAGE | Host | nx.images.url: Das Dokument ist kein Bild |
TOO_LARGE | Host | nx.images.url: Das Bild ist größer als 15 MB. nx.files.upload: Die Datei ist größer als 25 MB |
LIMIT | Host | Ein Limit wurde erreicht, etwa zu viele PDF-Viewer |
NETWORK | Host | Die Anfrage hat den Server nicht erreicht |
UNAUTHENTICATED | Host | Die Sitzung ist abgelaufen |
Zeigen Sie der Person error.message. Bei Prüffehlern ist die Meldung allgemein, und fieldErrors enthält die Einzelheiten: Eine Suche, die nach einem nicht indizierten Feld sortiert, scheitert mit „Die Suche ist ungültig.“ und fieldErrors.sort „Nach ‘notiz’ lässt sich nicht sortieren: das Feld ist nicht indexed.“
Farben und UI-Kit
Abschnitt betitelt „Farben und UI-Kit“Der Rahmen ist durchsichtig und folgt dem Farbschema von nexxus: <html data-theme="light"> oder "dark". Auf einer Datensatzseite liegt keine Karte dahinter: Ihre Ansicht steht direkt auf der Seite, wie die Abschnitte im Reiter Daten, also gehören ihre Inhalte in Karten (nx-card). Das UI-Kit ist eine CSS-Datei, die nexxus in jede Ansicht einfügt. Sie dürfen es ignorieren, mit ihm sieht Ihre Ansicht aber in beiden Farbschemata und in der Markenfarbe des Mandanten wie nexxus aus.
Farb- und Form-Tokens
Abschnitt betitelt „Farb- und Form-Tokens“| Variable | Verwendung |
|---|---|
--nx-text, --nx-text-muted, --nx-text-faint | Text, Nebentext, Hinweise |
--nx-surface, --nx-surface-raised, --nx-surface-sunken, --nx-page | Karten, Menüs, vertiefte Flächen, der Seitengrund |
--nx-line, --nx-line-soft | Rahmen und Trennlinien |
--nx-brand, --nx-brand-contrast, --nx-brand-ink | Markenfarbe als Fläche, Text darauf, Markenfarbe als Text |
--nx-accent, --nx-success, --nx-warning, --nx-danger, --nx-info | Signalfarben |
--nx-radius, --nx-radius-sm, --nx-shadow, --nx-font, --nx-font-mono | Form und Schrift |
Klassen
Abschnitt betitelt „Klassen“| Klasse | Für |
|---|---|
nx-btn mit nx-btn--primary, --danger, --quiet, --sm, --icon | Schaltflächen |
nx-badge mit nx-badge--success, --warning, --danger, --info, --brand | Statusetiketten |
nx-card, nx-card__title | Eine Karte |
nx-field, nx-field__label, nx-field__hint, nx-field__error, nx-input, nx-select, nx-textarea | Formulare; aria-invalid="true" markiert einen Fehler |
nx-list, nx-list__item (is-active) | Listen; ein <button class="nx-list__item"> ist anklickbar |
nx-rows, nx-entity-row (is-active), nx-meta | Datensätze so, wie nexxus seine Listen zeichnet; nx-list-compact an der Liste macht daraus Zeilen in einem Rahmen |
nx-table | Tabellen |
nx-empty, nx-empty__icon, nx-empty__title | Leere Zustände |
nx-title, nx-subtitle, nx-label, nx-muted, nx-faint, nx-mono, nx-num | Schrift |
nx-stack, nx-row, nx-spacer, nx-divider | Layout-Helfer |
nx-kbd, nx-progress (--nx-value), nx-spinner | Kleinigkeiten |
nx-pdf-slot | Die Fläche, die für ein PDF reserviert ist |
Ein PDF in der Ansicht
Abschnitt betitelt „Ein PDF in der Ansicht“Eine Ansicht kann ein PDF aus den Dateien zeigen, ohne je seine Bytes in der Hand zu haben. Sie reservieren ein Element, nexxus legt seinen eigenen PDF-Viewer darüber und lädt das Dokument mit den Rechten der Person, die es ansieht.
const handle = nx.pdf.mount(document.getElementById('pdf'), { documentId: 88, highlights: [{text: 'binnen zwei Wochen', page: 2}],});handle.on('select', ({page, text, rects}) => showNoteButton(page, text));handle.on('page', page => updatePageLabel(page));await handle.goTo(3);const {total, index} = await handle.find('Zustellung');await handle.setHighlights([{text: quote, page}]);await handle.destroy();- Geben Sie dem Element eine Größe, vor allem eine Höhe:
<div id="pdf" class="nx-pdf-slot"></div>. Der Viewer folgt dem Element, wenn es sich bewegt, scrollt oder seine Größe ändert, und wird dort abgeschnitten, wo Ihre scrollenden Container das Element abschneiden. - Ereignisse:
select({page, text, rects},rectsals Anteile 0 bis 1 der Seite, Ursprung oben links; eine aufgehobene Auswahl kommt mit leeremtext),page(die sichtbare Seite),load({pages}),error({code}).handle.readyerfüllt sich, sobald der Viewer steht. - Markierungen treffen unabhängig von Groß- und Kleinschreibung und Leerraum, über Zeilenumbrüche hinweg und auch dann, wenn typografische Anführungszeichen und Striche einfach getippt sind. Ohne
pagemarkiert der Viewer jedes Vorkommen.

Größe, Tasten und Dialoge
Abschnitt betitelt „Größe, Tasten und Dialoge“- Die Höhe folgt Ihrem Inhalt, bis zu 20 000 px. Eine
page-Ansicht füllt stattdessen den Bereich unter ihrer Oberkante (mindestens 320 px). Lassen Sie<html>bei seiner natürlichen Höhe, solange Sie keine Seite sind. - Tasten mit Strg, Cmd oder Alt sowie Escape gehen weiter an nexxus, es sei denn, Ihr Handler ruft
preventDefault()auf. Escape schließt deshalb den Dialog einerrecord.action-Ansicht. - Dialoge (
record.action): nexxus zeichnet den Kopf des Dialogs mit Beschriftung, Symbol und Schließen-Schaltfläche der Ansicht. Ihre Ansicht zeichnet den Inhalt und ihre eigenen Schaltflächen und endet mitnx.dialog.close(result). Wird der Dialog auf anderem Weg geschlossen, gilt die Aktion als nicht ausgeführt. Eine andere Ansicht des Moduls öffnet den Dialog mitnx.nav.open({view, id}). - Kacheln (
dashboard.widget): nexxus zeichnet die Karte mit Symbol, Beschriftung und Modulname, die Ansicht nur den Inhalt. Größen auf einem breiten Bildschirm:sein Viertel der Zeile,mdie Hälfte,ldie ganze Zeile.

| Was | Limit |
|---|---|
| Gleichzeitige Aufrufe je Ansicht | 32 |
| Meldungen (Toasts) | 20 pro Minute, mindestens 400 ms Abstand |
nx.storage je Person und Ansicht | 15 000 Zeichen als JSON; Schlüssel [A-Za-z0-9._-], höchstens 64 Zeichen |
| Datensatz-Nutzlast je Aufruf | 256 KB als JSON |
| Höhe der Ansicht | 20 000 px |
| PDF-Viewer je Ansicht | 4, mit bis zu 50 Markierungen von je 2 000 Zeichen |
| HTML-Datei | 2 MB |
Ansichten und der KI-Assistent
Abschnitt betitelt „Ansichten und der KI-Assistent“Paket-Module bringen keinen eigenen Chat mit. Der KI-Assistent von nexxus arbeitet auf jeder Paketseite, und eine Ansicht kann ihm sagen, was sie zeigt.
- Auf Listen-, Datensatz- und Seitenansichten teilt nexxus dem KI-Assistenten bereits Modul, Fachobjekt, Datensatz und Ansicht mit.
nx.assistant.setContext({summary, records})ergänzt, was nur Ihre Ansicht weiß, zum Beispiel „3 Geräte überfällig“ samt der Datensätze dahinter. Das erscheint als Chip in der Assistentenspalte und geht mit jeder Nachricht mit, solange die Ansicht zu sehen ist.nx.assistant.ask(prompt)öffnet die Assistentenspalte mit einem neuen Gespräch. Das klappt nur direkt nach einem Klick oder Tastendruck in Ihrer Ansicht, eine Ansicht kann also kein Gespräch von sich aus beginnen.- Die Beispiel-Anweisungen aus dem Manifest (
assistant.promptsmit einem Schlüsselview) erscheinen als Chips in der Assistentenspalte, solange diese Ansicht zu sehen ist.

Wie der KI-Assistent die Werkzeuge eines Moduls nutzt, beschreiben Mit dem KI-Assistenten arbeiten und Paketaufbau.
Das Protokoll, zur Fehlersuche
Abschnitt betitelt „Das Protokoll, zur Fehlersuche“Sie brauchen es selten, aber es hilft beim Lesen der Nachrichten im Browser.
- Das SDK schickt
{type: 'nxm:ready', sdk}an das übergeordnete Fenster. - nexxus prüft, dass die Nachricht aus dem eigenen Rahmen stammt (
event.source), und antwortet mit{type: 'nxm:connect'}und einemMessagePort. - Alles Weitere läuft über diesen Port: Anfragen
{t: 'req', id, method, params}, Antworten{t: 'res', id, ok, result}oder{t: 'res', id, ok: false, error}und Ereignisse{t: 'evt', name, data}in beide Richtungen.
Von nexxus an die Ansicht gehen die Ereignisse init, context, theme, record und pdf.*, von der Ansicht an nexxus height, key und pdf.rect. Die Methoden heißen records.search, records.get, records.create, records.update, records.remove, lookup, invoke, actions.preview, nav.open, ui.toast, ui.confirm, dialog.close, storage.get, storage.set, assistant.setContext, assistant.ask, images.get, pdf.mount, pdf.update, pdf.goTo, pdf.find und pdf.destroy.
Bekannte Lücken
Abschnitt betitelt „Bekannte Lücken“- Keine Modulbeschreibung in der Ansicht. Eine Ansicht kann die Feld- und Werte-Beschriftungen des Moduls nicht lesen. Wiederholen Sie die Beschriftungen, die Sie zeigen, mit
nx.t({de, en, pl})und halten Sie sie mit dem Manifest gleich. - Keine Rechte in der Ansicht. Eine Ansicht kann nicht fragen, ob die Person eine Aktion ausführen darf. Bieten Sie die Schaltfläche an und zeigen Sie die Meldung des Servers, wenn
FORBIDDENzurückkommt, oder legen Sie die Aktion in die Aktionsleiste des Datensatzes, die nexxus nur Personen zeigt, die sie ausführen dürfen. - Keine Symbolschrift. Verwenden Sie eingebettetes SVG.
Wenn etwas schiefgeht
Abschnitt betitelt „Wenn etwas schiefgeht“Kann eine Ansicht nicht laufen, zeigt nexxus an ihrer Stelle eine eigene Meldung:
| Meldung | Ursache und Abhilfe |
|---|---|
| „Diese Ansicht konnte nicht geladen werden.“ | Die Ansicht ließ sich nicht laden, etwa nach einem Netzwerkfehler. Erneut versuchen lädt sie noch einmal. |
| „Für diese Ansicht fehlt die Berechtigung.“ | Der Person fehlt ein Recht des Moduls. Geben Sie ihr eine Rolle des Pakets, siehe Rollen. |
| „Diese Ansicht gibt es nicht (mehr).“ | Den Ansichtsschlüssel gibt es in der installierten Version nicht, zum Beispiel weil ein Update ihn entfernt hat. |
| „Das Modul dieser Ansicht ist nicht aktiv.“ | Das Paket ist deaktiviert. Aktivieren Sie es auf seiner Paketseite. |
In Ihrer eigenen Ansicht sind die häufigsten Überraschungen ein fetch, das die Inhaltsrichtlinie sperrt (nehmen Sie nx.records), eine Sortierung oder ein Filter auf einem Feld ohne indexed (VALIDATION) und nx.assistant.ask ohne vorherigen Klick (NO_USER_ACTION).