KEPLIN Docs

Datastores und Daten

Wie ein Bildschirm Daten lädt, filtert und speichert — Datensatz- und Listen-Datastores, Schlüssel, Filter, Paginierung und die Datenbindungen.

Ein Bildschirm spricht nicht direkt mit der Datenbank: Er spricht mit Datastores — Datencontainern des Bildschirms, die Datensätze über die Tabellen-APIs der App laden. Die Widgets binden sich an die Datastores: Eine Tabelle zeigt die Zeilen eines Listen-Datastores, die Felder eines Formulars lesen und schreiben in einem Datensatz-Datastore.

Das ist das Bindeglied zwischen zwei Kapiteln: Die Tabellen-APIs werden über dem Datenmodell angelegt (Kapitel APIs & GraphQL); hier wird der Bildschirm an sie gebunden.

Die zwei Arten von Datastore

Art Was sie lädt Wofür
Datensatz EINEN Datensatz (oder einen neuen, leeren) Formulare: Die Felder binden sich an die Felder des Datensatzes, und am Ende wird gespeichert.
Liste Eine Sammlung von Datensätzen Tabellen, Listen, Karten, Diagramme, Kanbans, Kalender.

Datastores können an zwei Orten leben:

  • Auf dem Bildschirm — im Inspektor ohne Auswahl angelegt, in der Kategorie Daten. Sie sind geteilt: Mehrere Widgets können aus demselben lesen, und das ist es, was man für Formulare und für Master-Detail-Beziehungen verwendet.
  • In einem Widget — die Daten-Widgets (Tabelle, Diagramm, KPI…) haben ihren eigenen Datastore in ihrer Kategorie Daten. Das ist der häufigste Fall für eigenständige Grids und Diagramme.

Die Maschinerie ist an beiden Orten dieselbe; der einzige Unterschied liegt in den Wertquellen, die in den Filtern verfügbar sind (siehe die Bindungen).

Einen Datastore auf dem Bildschirm anlegen

  1. Klicken Sie auf eine leere Zone des Canvas, damit der Inspektor den Bildschirm zeigt.
  2. Klicken Sie in der Kategorie Daten auf + Datensatz oder + Liste.
  3. Klicken Sie auf den angelegten Datastore, um das Modal Datastore konfigurieren zu öffnen.
  4. Geben Sie ihm einen Name des Datastores — unter diesem Namen finden ihn die Widgets und der Code (z. B. conta, contas).
  5. Wählen Sie unter API die API, die die Daten liefert. Die Felder der API stehen dann für Spalten, Bindungen und Filter zur Verfügung. In einem Listen-Datastore erscheinen auch die Pipeline-APIs, mit dem Abzeichen pipeline: Sie liefern die ganze Liste, ohne Filter oder Seiten.

Die Kategorie Daten des Bildschirms Kontodatenblatt: der Datensatz-Datastore, der Listen-Datastore und die Buttons + Datensatz / + Liste.
Die Kategorie Daten des Bildschirms Kontodatenblatt: der Datensatz-Datastore, der Listen-Datastore und die Buttons + Datensatz / + Liste.

Hinweis

Ohne veröffentlichte Tabellen-APIs weist der Selektor darauf hin: Keine veröffentlichten Tabellen-APIs in dieser App. Legen Sie zuerst die API über der Entität des Modells an — das ist ein Schritt aus dem Kapitel APIs & GraphQL.

Datensatz-Datastore — welcher Datensatz geladen wird

Ein Datensatz-Datastore antwortet auf eine Frage: welcher Datensatz? Die Antwort geben Sie unter Welcher Datensatz geladen wird (Schlüssel):

  1. Klicken Sie auf + Schlüsselfeld.
  2. Wählen Sie das Feld (standardmäßig der Primärschlüssel), den Operator und den Wert — typischerweise ein Param der Route: Der Bildschirm Kontodatenblatt erhält id in der Adresse und lädt das Konto mit dieser id.
  3. Mehrere Bedingungen bilden einen zusammengesetzten Schlüssel — alle müssen passen.

Ohne Bedingungen lädt der Datastore einen neuen (leeren) Datensatz — so taugt derselbe Formularbildschirm auch zum Anlegen: ohne id geöffnet, beginnt er leer; gespeichert, macht er das Insert.

Finden die Bedingungen keinen Datensatz (eine id, die nicht mehr existiert oder außerhalb der Reichweite der Rolle liegt, die den Bildschirm öffnet), meldet die App, dass der angeforderte Datensatz nicht existiert, und das Formular speichert nicht. Nur ein Schlüssel, der in ein Feld des Bildschirms eingegeben wird (ein natürlicher Schlüssel, etwa eine Artikelnummer), bleibt der Schlüssel eines neuen Datensatzes.

Listen-Datastore — Filter und Laden

Filter (where)

Die Filter (where) sind Bedingungen, die bei jedem Lesen der Daten gelten — hier wird begrenzt, was aus der Datenbank kommt. Jede Bedingung besteht aus Feld / Operator / Wert; + Filter hinzufügen ergänzt Bedingungen, und + Gruppe erzeugt verschachtelte Untergruppen, wobei Alle (AND) oder Beliebige (OR) entscheidet, wie sie sich verbinden.

Beispiel aus der Kundenverwaltung: Der Bildschirm Konten filtert estado eq "activa"; das Panel „meine Konten“ ergänzt gestor eq → Sitzung ▸ username.

Die Operatoren:

Operator Was er vergleicht
eq / neq Gleich / ungleich dem Wert. neq schließt Datensätze mit leerem Feld ein.
contains, startsWith, endsWith Text, der den Wert enthält, damit beginnt oder endet.
gt, gte, lt, lte Größer, größer oder gleich, kleiner, kleiner oder gleich — Zahlen und Daten.
in / nin Eines von / keines von einer Werteliste. Der Wert ist eine Liste: mehrere durch Kommas getrennte Werte oder der Wert einer Liste mit Mehrfachauswahl, gebunden über Widget — so wird eine Tabelle nach mehreren Zentren oder mehreren Zuständen zugleich gefiltert. nin schließt Datensätze mit leerem Feld ein.

Eine Bedingung mit leerem Wert (leeres Suchfeld, Liste ohne Auswahl) filtert nichts — der Bildschirm zeigt alles, bis die Person wählt.

Jeder Filterwert wird nach dem Typ der Spalte umgewandelt: In einer Textspalte bleiben eine Steuernummer oder eine Postleitzahl („0012“) Text, und in einer Dezimalspalte ist „12,5“ eine Zahl.

Laden und Seite

Option Was sie tut
Alles laden Holt alle Datensätze des Filters auf einmal — Blättern, Sortieren und Filtern auf dem Bildschirm wird sofort wirksam.
Seite für Seite Geht bei jedem Seitenwechsel zum Server — für große Tabellen, bei denen alles zu holen keinen Sinn ergibt.
Pro Seite Wie viele Zeilen auf dem Bildschirm gleichzeitig zu sehen sind — nicht zu verwechseln damit, wie viele Datensätze gelesen werden.
Automatisch laden Die Daten lesen, sobald der Bildschirm geöffnet wird. Schalten Sie es aus, um erst nach einer Aktion zu laden (etwa einem Button „Suchen“).

Ohne Automatisch laden liest die Liste, wenn jemand sie dazu auffordert: ein reload() (etwa auf einer Schaltfläche „Suchen“), ein Seiten- oder Sortierwechsel oder ein angewendeter Filter. Ein geändertes Feld auf dem Bildschirm lässt sie nicht von selbst lesen.

Wenn sich der wirksame Filter ändert (ein Feld auf dem Bildschirm, ein Parameter, der App-Zustand), springt die Liste zur ersten Seite zurück. Existiert die Seite, auf der Sie waren, nicht mehr (etwa weil Sie den letzten Datensatz der letzten Seite gelöscht haben), wechselt die Liste zur letzten vorhandenen Seite.

Tipp

Nutzen Sie in beiden Modi die Filter (where), um zu begrenzen, was gelesen wird. „Alles laden“ mit einem anständigen Filter ist schnell; ohne jeden Filter heißt es, die ganze Tabelle anzufordern.

Die Bindungen — woher ein Wert kommt

Immer wenn ein Filter, ein Schlüssel oder eine Eigenschaft einen Wert braucht, verwenden Sie dasselbe Teil: die Bindung. Der erste Selektor nennt die Quelle; der Rest ändert sich mit ihr:

Quelle Was sie ist
Fest Ein Wert, der direkt dort eingetragen wird, gleich für alle.
Param Ein Parameter der Route des Bildschirms (Abschnitt Routen-Parameter).
Sitzung Ein Feld des angemeldeten Benutzers (userId, username, name).
Zustand Ein Wert, der mit keplin.state.set() im Speicher der App abgelegt wird — auf jedem Bildschirm verfügbar.
Datastore Ein Feld aus einem anderen Datastore des Bildschirms — die Grundlage von Master-Detail.
Widget Der aktuelle Wert eines anderen Eingabe-Widgets — die Grundlage interaktiver Filter.

Auch ein Feld schreibt in den Zustand: Wählen Sie in der Datenbindung des Feldes die Option Zustand und geben Sie den Schlüssel ein. Ein Filter mit der Quelle Zustand und demselben Schlüssel liest die Daten neu, wenn sich der Wert ändert. So filtert ein Widget-Bereich der Leiste die Seiten; siehe Navigation der App.

Die Quellen Datastore und Widget gibt es nur in den Datastores innerhalb von Widgets — sie hängen vom Rest des Bildschirms ab. In den Datastores des Bildschirms bleiben die ersten vier.

Mit diesen Teilen baut man die Alltagsmuster ohne Code:

  • Master-Detail — die Opportunity-Tabelle des Kontos: im Datastore der Tabelle der Filter contaId eq → Datastore ▸ conta ▸ id. Ein anderes Konto auszuwählen lädt das Detail neu.
  • Filter über Text — ein Textfeld „suchen“ und, im Datastore der Tabelle, nome contains → Widget ▸ das Textfeld. (Um erst beim Klick auf einen Button zu filtern, geht man über ein Ereignis — siehe Ereignisse und das SDK.)

Formularfelder an einen Datensatz binden

Jedes Formularfeld hat in der Kategorie Daten den Abschnitt Datenbindung: Wählen Sie den Datensatz-Datastore und das Feld. Von da an zeigt die Eingabe den geladenen Wert, und die Änderungen bleiben im Datastore — ungespeichert — bis jemand speichert.

Der letzte Schritt ist ein Button, dessen Ereignis speichert:

const ok = await keplin.data.store("conta").save();
if (ok) {
  keplin.ui.toast("Gespeichert.", "success");
}

Dieser Code ist genau das, was die vordefinierte Aktion Datastore speichern des Ereignis-Editors für Sie einfügt. save() validiert zuerst (Pflichtfelder, Regeln, Validierungsskripte) und speichert nur, wenn alles besteht; es gibt true zurück, wenn gespeichert wurde.

Beim Speichern eines bereits vorhandenen Datensatzes werden nur die Felder gesendet, die sich seit dem Lesen geändert haben. Ein geleertes Feld wird leer gespeichert (NULL in der Datenbank), und in einem Dezimalfeld wird „12,5“ als Zahl gelesen.

Der Bildschirm Kontodatenblatt: Formularfelder, an den Datensatz-Datastore gebunden, bereit zum Speichern.
Der Bildschirm Kontodatenblatt: Formularfelder, an den Datensatz-Datastore gebunden, bereit zum Speichern.

Mit ungespeicherten Änderungen fragt das Verlassen der Seite nach einer Bestätigung: über die Menüs, über die Zurück-Schaltfläche des Browsers oder beim Schließen des Tabs. Ein Modal fragte schon beim Schließen. Navigation per Code (keplin.nav.go) fragt nicht: Wer sie aufruft, hat schon entschieden und oft gerade gespeichert.

Beim Speichern eines neuen Datensatzes wird ein Feld, das der Bildschirm nicht zeigt, nicht gesendet: In einer Spalte mit Standardwert in der Datenbank, oder von ihr erzeugt, gilt dieser Wert; eine Pflichtspalte ohne Standardwert muss auf dem Bildschirm sein, und das Formular sagt, welche fehlt. Ein in ein Feld des Bildschirms eingegebener Schlüssel (ein natürlicher Schlüssel, etwa ein Artikelcode) gehört zu einem neuen Datensatz; per Code mit set() gesetzt, bleibt er der Schlüssel eines zu ändernden Datensatzes. Einen inzwischen nicht mehr existierenden Datensatz zu speichern ergibt einen Fehler statt „Gespeichert“.

Das Modal Datastore konfigurieren, Feld für Feld

Das Modal Datastore konfigurieren: API, Schlüssel/Filter, Laden und Seite.
Das Modal Datastore konfigurieren: API, Schlüssel/Filter, Laden und Seite.

Feld Datensatz Liste
Name des Datastores ✓ ✓
API ✓ ✓
Welcher Datensatz geladen wird (Schlüssel) ✓ —
Filter (where) — ✓
Laden / Pro Seite — ✓
Automatisch laden ✓ ✓

Datastores auf öffentlichen Bildschirmen

Auf einem als Öffentlicher Bildschirm (ohne Sitzung) markierten Bildschirm kommen die Daten ausschließlich aus APIs mit öffentlichem Lesezugriff: Der Selektor zeigt nur diese, und eine bereits gewählte API, die nicht öffentlich ist, wird gekennzeichnet — Diese API hat keinen öffentlichen Lesezugriff — auf einem Bildschirm ohne Sitzung lädt sie keine Daten. Der Lesezugriff wird im API-Editor als öffentlich markiert.

Die Daten im Code

Alles, was die Datastores tun, steht auch im SDK der Ereignisse — keplin.data.store("name") gibt den Datastore über seinen Namen zurück, mit reload(), setWhere(), get()/set()/save() und Gefährten. Das Kapitel Ereignisse und das SDK geht es durch.

Warum nicht…?

  • Warum lädt es keine Daten? Prüfen Sie in dieser Reihenfolge: Ist Automatisch laden eingeschaltet? Existiert die gewählte API und ist sie veröffentlicht? Ist auf einem öffentlichen Bildschirm der Lesezugriff der API öffentlich? Schließt der Filter nicht alles aus?
  • Warum öffnet sich immer ein leerer Datensatz? Der Datensatz-Datastore hat keine Bedingungen unter Welcher Datensatz geladen wird (Schlüssel) — oder der in der Bedingung verwendete Parameter kommt in der Route nicht an.
  • Warum erscheint die neue Spalte nicht, nachdem ich das Modell geändert habe? Der Datastore hält ein Abbild der Felder der API von dem Moment, in dem Sie sie gewählt haben. Öffnen Sie Datastore konfigurieren erneut und wählen Sie die API neu, um das Abbild zu aktualisieren. Was jede bereits gewählte Spalte ist (Typ, Pflicht oder nicht, Standardwert, Datum), aktualisiert sich beim Öffnen des Bildschirms von selbst; nur neue Spalten müssen gewählt werden.
  • Warum ist die Paginierung langsam? Sie sind in Seite für Seite mit vielen Gängen zum Server — oder in Alles laden ohne Filter in einer riesigen Tabelle. Passen Sie den Modus an die echte Größe der Daten an.