Datastores en gegevens
Hoe een scherm gegevens laadt, filtert en opslaat — record- en lijst-datastores, sleutels, filters, paginering en de gegevenskoppelingen.
Een scherm praat niet rechtstreeks met de database: het praat met datastores — gegevenscontainers van het scherm die records laden via de tabel-API's van de app. De widgets koppelen aan de datastores: een Tabel toont de rijen van een lijst-datastore, de velden van een formulier lezen uit en schrijven naar een record-datastore.
Dit is de schakel tussen twee hoofdstukken: de tabel-API's maakt u op het gegevensmodel (hoofdstuk API's & GraphQL); hier koppelt u het scherm eraan.
De twee soorten datastore
| Soort | Wat die laadt | Waarvoor |
|---|---|---|
| Record | ÉÉN record (of een nieuw, leeg record) | Formulieren: de velden koppelen aan de velden van het record, en aan het eind slaat u op. |
| Lijst | Een verzameling records | Tabellen, lijsten, kaarten, grafieken, kanbans, kalenders. |
Datastores kunnen op twee plekken leven:
- Op het scherm — aangemaakt in de inspector zonder selectie, in de categorie Gegevens. Zij worden gedeeld: meerdere widgets kunnen uit dezelfde lezen, en dat is wat u voor formulieren en voor master-detailrelaties gebruikt.
- Binnen een widget — de gegevenswidgets (Tabel, Grafiek, KPI…) hebben hun eigen datastore in hun categorie Gegevens. Dat is het meest voorkomende geval voor onafhankelijke grids en grafieken.
De motor is op beide plekken dezelfde; het enige verschil zit in de waardebronnen die in de filters beschikbaar zijn (zie de koppelingen).
Een datastore op het scherm aanmaken
- Klik op een lege zone van het canvas zodat de inspector het scherm toont.
- Klik in de categorie Gegevens op + record of + lijst.
- Klik op de aangemaakte datastore om het modale venster Datastore instellen te openen.
- Geef hem een Naam van de datastore — met deze naam vinden de widgets en
de code hem terug (bijv.:
conta,contas). - Kies bij API de API die de gegevens levert. De velden van de API komen beschikbaar voor kolommen, koppelingen en filters. In een lijst-datastore verschijnen ook de pipeline-API's, met het label pipeline: ze geven de hele lijst terug, zonder filters of paginering.

Opmerking
Zonder gepubliceerde tabel-API's waarschuwt de keuzelijst: Geen gepubliceerde tabel-API's in deze app. Maak eerst de API op de entiteit van het model — dat is een stap uit het hoofdstuk API's & GraphQL.
Record-datastore — welk record te laden
Een record-datastore beantwoordt één vraag: welk record? Het antwoord geeft u bij Welk record te laden (sleutel):
- Klik op + sleutelveld.
- Kies het veld (standaard de primaire sleutel), de operator en de waarde —
meestal een Param uit de route: het scherm Ficha de Conta ontvangt
idin het adres en laadt de account met dat id. - Meerdere voorwaarden vormen een samengestelde sleutel — ze moeten allemaal kloppen.
Zonder voorwaarden laadt de datastore een nieuw (leeg) record — zo dient
hetzelfde formulierscherm ook om aan te maken: zonder id geopend begint het
blanco; opgeslagen doet het de invoeging.
Vinden de voorwaarden geen enkel record (een id dat niet meer bestaat, of
buiten het bereik van de rol van wie het scherm opent), dan meldt de app dat
het gevraagde record niet bestaat en slaat het formulier niet op. Alleen een
sleutel die in een veld van het scherm wordt getypt (een natuurlijke sleutel,
zoals een artikelcode) blijft die van een nieuw record.
Lijst-datastore — filters en laden
Filters (where)
De Filters (where) zijn voorwaarden die gelden telkens wanneer de gegevens gelezen worden — hier beperkt u wat er uit de database komt. Elke voorwaarde is veld / operator / waarde; + filter toevoegen voegt voorwaarden toe en + groep maakt geneste subgroepen, waarbij Alle (AND) of Elke (OR) bepaalt hoe ze gecombineerd worden.
Voorbeeld uit Klantenbeheer: het scherm Contas filtert estado eq "activa";
het paneel "mijn accounts" voegt gestor eq → Sessie ▸ username toe.
De operators:
| Operator | Wat hij vergelijkt |
|---|---|
eq / neq |
Gelijk / niet gelijk aan de waarde. neq omvat ook records met een leeg veld. |
contains, startsWith, endsWith |
Tekst die de waarde bevat, ermee begint of eindigt. |
gt, gte, lt, lte |
Groter, groter of gelijk, kleiner, kleiner of gelijk — getallen en datums. |
in / nin |
Een van / geen van een lijst waarden. De waarde is een lijst: meerdere waarden gescheiden door komma's, of die van een Lijst met Meervoudige selectie gekoppeld via Widget — zo filter je een tabel op meerdere centra of meerdere statussen tegelijk. nin omvat ook records met een leeg veld. |
Een voorwaarde met een lege waarde (leeg zoekvak, lijst zonder keuze) filtert niets — het scherm toont alles totdat de persoon kiest.
Elke filterwaarde wordt omgezet volgens het type van de kolom: in een tekstkolom blijven een fiscaal nummer of een postcode (“0012”) tekst, en in een decimale kolom is “12,5” een getal.
Laden en pagina
| Optie | Wat die doet |
|---|---|
| Alles laden | Haalt alle records van het filter in één keer op — van pagina wisselen, sorteren en filteren op het scherm gaat dan direct. |
| Eén pagina per keer | Gaat bij elke paginawissel naar de server — voor grote tabellen, waar alles ophalen geen zin heeft. |
| Per pagina | Hoeveel rijen er tegelijk op het scherm te zien zijn — niet te verwarren met hoeveel records er gelezen worden. |
| Automatisch laden | De gegevens lezen zodra het scherm opent. Schakel dit uit als u pas na een actie wilt laden (een knop "Zoeken", bijvoorbeeld). |
Zonder Automatisch laden leest de lijst wanneer iemand erom vraagt: een
reload() (op een knop “Zoeken”, bijvoorbeeld), een wissel van pagina of
sortering, of een toegepast filter. Een veld op het scherm wijzigen laat haar
niet vanzelf lezen.
Wanneer het effectieve filter verandert (een veld op het scherm, een parameter, de app-status), gaat de lijst terug naar de eerste pagina. Bestaat de pagina waarop u stond niet meer (u hebt bijvoorbeeld het laatste record van de laatste pagina verwijderd), dan gaat de lijst naar de laatste pagina die bestaat.
Tip
Gebruik in beide modi de Filters (where) om te beperken wat er gelezen wordt. "Alles laden" met een fatsoenlijk filter is snel; zonder enig filter vraagt u de hele tabel op.
De koppelingen — waar een waarde vandaan komt
Telkens wanneer een filter, een sleutel of een eigenschap een waarde nodig heeft, gebruikt u hetzelfde stuk: de koppeling. De eerste keuzelijst noemt de bron; de rest verandert daarmee mee:
| Bron | Wat het is |
|---|---|
| Vast | Een waarde die u daar ter plekke invult, gelijk voor iedereen. |
| Param | Een routeparameter van het scherm (sectie Routeparameters). |
| Sessie | Een veld van de aangemelde gebruiker (userId, username, name). |
| State | Een waarde die met keplin.state.set() in het geheugen van de app bewaard is — beschikbaar op elk scherm. |
| Datastore | Een veld uit een andere datastore van het scherm — de basis van master-detail. |
| Widget | De huidige waarde van een andere invoerwidget — de basis van de interactieve filters. |
Ook een veld schrijft in de state: kies in de Gegevenskoppeling van het veld de optie State en typ de Sleutel. Een filter met de bron State en dezelfde sleutel leest de gegevens opnieuw als de waarde verandert. Zo filtert een widgetgebied op de balk de pagina's; zie Navigatie van de app.
De bronnen Datastore en Widget bestaan alleen in de datastores binnen widgets — zij hangen af van de rest van het scherm. In de datastores van het scherm blijven de eerste vier over.
Met deze stukken bouwt u de dagelijkse patronen zonder code:
- Master-detail — de tabel met kansen van de account: in de datastore van de
tabel het filter
contaId eq→ Datastore ▸conta▸id. Een andere account selecteren laadt het detail opnieuw. - Filter op tekst — een Tekstvak "zoeken" en, in de datastore van de tabel,
nome contains→ Widget ▸ het tekstvak. (Om pas te filteren bij een klik op een knop, doet u dat via een gebeurtenis — zie Gebeurtenissen en de SDK.)
Formuliervelden aan een record koppelen
Elk formulierveld heeft, in de categorie Gegevens, de sectie Gegevenskoppeling: kies de record-datastore en het veld. Vanaf dat moment toont het invoerveld de geladen waarde en blijven de wijzigingen in de datastore staan — niet opgeslagen — tot iemand opslaat.
De laatste stap is een knop waarvan de gebeurtenis opslaat:
const ok = await keplin.data.store("conta").save();
if (ok) {
keplin.ui.toast("Opgeslagen.", "success");
}
Deze code is precies wat de vooraf bepaalde actie Datastore opslaan van de
gebeurtenis-editor voor u invoegt. save() valideert eerst (verplichte velden,
regels, validatiescripts) en slaat alleen op als alles slaagt; het geeft true
terug als er opgeslagen is.
Bij het opslaan van een record dat al bestond, gaan alleen de velden mee die sinds het lezen zijn gewijzigd. Een leeggemaakt veld wordt leeg opgeslagen (null in de database), en in een decimaal veld wordt “12,5” als getal gelezen.

Met niet-opgeslagen wijzigingen vraagt het verlaten van de pagina om
bevestiging: via de menu's, via de knop Terug van de browser of bij het
sluiten van het tabblad. Een modal vroeg dat al bij het sluiten. Navigatie
via code (keplin.nav.go) vraagt niets: wie ze aanroept, heeft al beslist en
heeft vaak net opgeslagen.
Bij het opslaan van een nieuw record wordt een veld dat het scherm niet toont
niet verzonden: in een kolom met een standaardwaarde in de database, of door
de database gegenereerd, geldt die waarde; een verplichte kolom zonder
standaardwaarde moet op het scherm staan, en het formulier zegt welke
ontbreekt. Een sleutel die in een veld van het scherm is getypt (een
natuurlijke sleutel, zoals een artikelcode) hoort bij een nieuw record; via
code gezet met set() blijft het de sleutel van een record om te wijzigen.
Een record opslaan dat intussen niet meer bestaat, geeft een fout en niet
"Opgeslagen".
Het modale venster Datastore instellen, veld voor veld

| Veld | Record | Lijst |
|---|---|---|
| Naam van de datastore | ✓ | ✓ |
| API | ✓ | ✓ |
| Welk record te laden (sleutel) | ✓ | — |
| Filters (where) | — | ✓ |
| Laden / Per pagina | — | ✓ |
| Automatisch laden | ✓ | ✓ |
Datastores op openbare schermen
Op een scherm dat als Openbaar scherm (zonder sessie) gemarkeerd is, komen de gegevens alleen uit API's met openbare leestoegang: de keuzelijst toont alleen die, en een al gekozen API die niet openbaar is, wordt gemarkeerd — Deze API heeft geen openbare leestoegang — op een scherm zonder sessie laadt zij geen gegevens. Het lezen markeert u als openbaar in de editor van de API.
De gegevens in de code
Alles wat de datastores doen zit ook in de SDK van de gebeurtenissen —
keplin.data.store("naam") geeft de datastore op naam terug, met reload(),
setWhere(), get()/set()/save() en aanverwanten. Het hoofdstuk
Gebeurtenissen en de SDK loopt die langs.
Waarom niet…?
- Waarom laadt hij geen gegevens? Kijk, op volgorde: staat Automatisch laden aan? Bestaat de gekozen API en is zij gepubliceerd? Is op een openbaar scherm het lezen van de API openbaar? Sluit het filter niet alles uit?
- Waarom opent er altijd een leeg record? De record-datastore heeft geen voorwaarden bij Welk record te laden (sleutel) — of de parameter die in de voorwaarde gebruikt wordt, komt niet in de route aan.
- Waarom verschijnt de nieuwe kolom niet nadat ik het model gewijzigd heb? De datastore bewaart een momentopname van de velden van de API van toen u haar koos. Open Datastore instellen opnieuw en kies de API nogmaals om de momentopname bij te werken. Wat elke al gekozen kolom is (type, verplicht of niet, standaardwaarde, datum) wordt vanzelf bijgewerkt bij het openen van het scherm; alleen nieuwe kolommen moeten worden gekozen.
- Waarom is de paginering traag? U staat op Eén pagina per keer met veel gangen naar de server — of op Alles laden zonder filters op een enorme tabel. Stem de modus af op de werkelijke omvang van de gegevens.