Datastores e dados
Como um ecrã carrega, filtra e grava dados — datastores de registo e de lista, chaves, filtros, paginação e as ligações a dados.
Um ecrã não fala directamente com a base de dados: fala com datastores — contentores de dados do ecrã que carregam registos através das APIs de tabela da app. Os widgets ligam-se aos datastores: uma Tabela mostra as linhas de um datastore de lista, os campos de um formulário lêem e escrevem num datastore de registo.
Este é o elo entre dois capítulos: as APIs de tabela criam-se sobre o modelo de dados (capítulo APIs & GraphQL); aqui liga-se o ecrã a elas.
Os dois tipos de datastore
| Tipo | O que carrega | Para quê |
|---|---|---|
| Registo | UM registo (ou um registo novo, vazio) | Formulários: os campos ligam-se aos campos do registo, e no fim grava-se. |
| Lista | Uma colecção de registos | Tabelas, listas, cartões, gráficos, kanbans, calendários. |
Os datastores podem viver em dois sítios:
- No ecrã — criados no inspector sem selecção, na categoria Dados. São partilhados: vários widgets podem ler do mesmo, e é o que se usa para formulários e para relações mestre-detalhe.
- Dentro de um widget — os widgets de dados (Tabela, Gráfico, KPI…) têm o seu próprio datastore na categoria Dados deles. É o caso mais comum para grelhas e gráficos independentes.
O motor é o mesmo nos dois sítios; a única diferença está nas origens de valor disponíveis nos filtros (ver as ligações).
Criar um datastore no ecrã
- Clica numa zona vazia do canvas para o inspector mostrar o ecrã.
- Na categoria Dados, clica em + registo ou + lista.
- Clica no datastore criado para abrir o modal Configurar datastore.
- Dá-lhe um Nome do datastore — é por este nome que os widgets e o
código o encontram (ex.:
conta,contas). - Em API de tabela, escolhe a API que serve os dados. Os campos da API ficam disponíveis para colunas, ligações e filtros.

Nota
Sem APIs de tabela publicadas, o selector avisa: Sem APIs de tabela publicadas nesta app. Cria primeiro a API sobre a entidade do modelo — é um passo do capítulo APIs & GraphQL.
Datastore de registo — que registo carregar
Um datastore de registo responde a uma pergunta: qual registo? A resposta dá-se em Que registo carregar (chave):
- Clica em + campo da chave.
- Escolhe o campo (por omissão, a chave primária), o operador e o valor —
tipicamente um Param da rota: o ecrã Ficha de Conta recebe
idno endereço e carrega a conta com esse id. - Várias condições formam uma chave composta — todas têm de bater.
Sem condições, o datastore carrega um registo novo (vazio) — é assim que
o mesmo ecrã de formulário serve para criar: aberto sem id, começa em
branco; gravado, faz a inserção.
Datastore de lista — filtros e carregamento
Filtros (where)
Os Filtros (where) são condições aplicadas sempre que os dados são lidos — é aqui que se limita o que vem da base de dados. Cada condição é campo / operador / valor; + adicionar filtro acrescenta condições e + grupo cria sub-grupos aninhados, com Todas (AND) ou Qualquer (OR) a decidir como se combinam.
Exemplo da Gestão de Clientes: o ecrã Contas filtra estado eq "activa";
o painel "as minhas contas" acrescenta gestor eq → Sessão ▸ username.
Carregamento e página
| Opção | O que faz |
|---|---|
| Carregar tudo | Traz todos os registos do filtro de uma vez — mudar de página, ordenar e filtrar no ecrã fica instantâneo. |
| Uma página de cada vez | Vai ao servidor a cada mudança de página — para tabelas grandes, onde trazer tudo não faz sentido. |
| Por página | Quantas linhas se vêem de cada vez no ecrã — não confundir com quantos registos são lidos. |
| Carregar automaticamente | Ler os dados assim que o ecrã abre. Desliga se preferires carregar só depois de uma acção (um botão "Pesquisar", por exemplo). |
Dica
Em qualquer dos modos, usa os Filtros (where) para limitar o que é lido. "Carregar tudo" com um filtro decente é rápido; sem filtro nenhum, é pedir a tabela inteira.
As ligações — de onde vem um valor
Sempre que um filtro, uma chave ou uma propriedade precisa de um valor, usas a mesma peça: a ligação. O primeiro selector diz a origem; o resto muda conforme ela:
| Origem | O que é |
|---|---|
| Fixo | Um valor escrito ali mesmo, igual para todos. |
| Param | Um parâmetro da rota do ecrã (secção Parâmetros de rota). |
| Sessão | Um campo do utilizador com sessão iniciada (userId, username, name). |
| Estado | Um valor guardado na memória da app com keplin.state.set() — disponível em todos os ecrãs. |
| Datastore | Um campo de outro datastore do ecrã — a base do mestre-detalhe. |
| Widget | O valor actual de outro widget de input — a base dos filtros interactivos. |
As origens Datastore e Widget só existem nos datastores dentro de widgets — dependem do resto do ecrã. Nos datastores do ecrã ficam as quatro primeiras.
Com estas peças montam-se os padrões do dia-a-dia sem código:
- Mestre-detalhe — a tabela de oportunidades da conta: no datastore da
tabela, filtro
contaId eq→ Datastore ▸conta▸id. Seleccionar outra conta recarrega o detalhe. - Filtro por texto — uma Caixa de texto "procurar" e, no datastore da
tabela,
nome contains→ Widget ▸ a caixa. (Para filtrar só ao clicar num botão, faz-se por evento — ver Eventos e o SDK.)
Ligar campos de formulário a um registo
Cada campo de formulário tem, na categoria Dados, a secção Ligação a dados: escolhe o datastore de registo e o campo. A partir daí o input mostra o valor carregado e as alterações ficam no datastore — por gravar — até alguém gravar.
O passo final é um botão cujo evento grava:
const ok = await keplin.data.store("conta").save();
if (ok) {
keplin.ui.toast("Gravado.", "success");
}
Este código é exactamente o que a acção pré-definida Gravar datastore do
editor de eventos insere por ti. save() valida primeiro (obrigatórios,
regras, scripts de validação) e só grava se tudo passar; devolve true se
gravou.

O modal Configurar datastore, campo a campo

| Campo | Registo | Lista |
|---|---|---|
| Nome do datastore | ✓ | ✓ |
| API de tabela | ✓ | ✓ |
| Que registo carregar (chave) | ✓ | — |
| Filtros (where) | — | ✓ |
| Carregamento / Por página | — | ✓ |
| Carregar automaticamente | ✓ | ✓ |
Datastores em ecrãs públicos
Num ecrã marcado Ecrã público (sem sessão), os dados vêm apenas de APIs com leitura pública: o selector só mostra essas, e uma API já escolhida que não seja pública fica assinalada — Esta API não tem leitura pública — num ecrã sem sessão não carrega dados. A leitura marca-se como pública no editor da API.
Os dados no código
Tudo o que os datastores fazem está também no SDK dos eventos —
keplin.data.store("nome") devolve o datastore pelo nome, com reload(),
setWhere(), get()/set()/save() e companhia. O capítulo
Eventos e o SDK percorre-o.
Porque não…?
- Porque não carrega dados? Vê, por ordem: Carregar automaticamente está ligado? A API escolhida existe e está publicada? Num ecrã público, a leitura da API é pública? O filtro não está a excluir tudo?
- Porque abre sempre um registo vazio? O datastore de registo não tem condições em Que registo carregar (chave) — ou o parâmetro usado na condição não está a chegar na rota.
- Porque mudei o modelo e a coluna nova não aparece? O datastore guarda um retrato dos campos da API de quando a escolheste. Reabre Configurar datastore e volta a escolher a API para actualizar o retrato.
- Porque é que a paginação está lenta? Estás em Uma página de cada vez com muitas idas ao servidor — ou em Carregar tudo sem filtros numa tabela enorme. Ajusta o modo ao tamanho real dos dados.