Toda aplicação de negócio contém a mesma página, escrita de novo para cada tabela: uma lista com uma caixa de busca e um paginador, um formulário para criar e editar, uma confirmação de exclusão, e o código que escreve. Nosso próprio demo de administração tinha quatro manipuladores de requisição e cerca de quatrocentas linhas de construtores de página só para clientes, e depois o mesmo de novo para fornecedores, e de novo para faturas.
O sgcWebSockets 2026.10 adiciona o TsgcHTMLComponent_CRUD, que é dono dessa página. O demo agora constrói a área de clientes com um adaptador de seis métodos, e mantém a versão escrita à mão ao lado para que você possa ler as duas.
A página
uses
sgcHTML_Component_CRUD;
FCRUD := TsgcHTMLComponent_CRUD.Create(Self);
FCRUD.CRUDID := 'customers';
FCRUD.RoutePrefix := '/customers';
FCRUD.Title := 'Customers';
FCRUD.KeyField := 'ID';
FCRUD.PageSize := 15;
FCRUD.Actions := [caCreate, caEdit, caDelete, caView, caExport];
FCRUD.DataSet := FDQueryCustomers;
Vinculado a um dataset, ele lê suas próprias colunas, e isso é a página inteira: lista, busca, paginação, o formulário de criação e edição, a confirmação de exclusão e uma exportação CSV de tudo o que a lista está exibindo.
Ou o seu próprio SQL
Um dataset é uma forma de armazenar registros, não a única. Tudo o que altera um registro passa por um adaptador, então o componente nunca vê SQL, um registro ou um driver de banco de dados:
type
TCustomersAdapter = class(TsgcHTMLCRUDAdapter)
public
function Locate(const aKey: string): Boolean; override;
function Read(const aKey: string; aValues: TStrings): Boolean; override;
function List(const aSearch: string; aPage, aPageSize: Integer;
aRows: TStrings): Integer; override;
function Insert(aValues: TStrings; var aKey: string;
aErrors: TStrings): Boolean; override;
function Update(const aKey: string; aValues, aErrors: TStrings)
: Boolean; override;
function Delete(const aKey: string; aErrors: TStrings): Boolean; override;
end;
FCRUD.SetAdapter(TCustomersAdapter.Create(FCRUD));
Seis métodos sobre o que você já tem. No demo, cada um é uma única chamada ao pool de banco de dados da aplicação.
As partes que você teria escrito depois
Bloqueio otimista. Informe uma coluna de versão e uma gravação compara o que o navegador envia com o que está armazenado, de modo que a segunda pessoa a clicar em Salvar é avisada de que o registro mudou, em vez de sobrescrever silenciosamente o primeiro:
FCRUD.VersionField := 'UPDATED_AT';
Mestre e detalhe. As listas filhas de um registro são outros componentes CRUD, renderizados sob o formulário enquanto o registro está sendo editado:
with FCRUD.Details.Add do
begin
CRUD := FCRUDOrderLines;
MasterField := 'ORDER_ID';
Caption := 'Lines';
end;
Validação que é sobre os seus dados, não sobre formulários. As colunas obrigatórias são trabalho do componente; OnValidate é onde vivem as regras que são sobre os clientes. Adicione uma linha por problema e a gravação é recusada e o formulário volta com elas.
Duas formas de começar
Na IDE agora há um assistente: Tools › New sgcHTML CRUD page. Informe a tabela, a chave e as colunas, e o componente é criado no formulário em edição, com as duas linhas que o conectam já na área de transferência.
Fora da IDE há uma ferramenta de linha de comando, sgcHTMLGen, que escreve o código-fonte da página em Object Pascal ou em C#:
sgcHTMLGen crud --table Customers --prefix /customers ^
--fields "ID:key CODE:req:32 NAME:req:120 CITY:80 NOTES:noform"
Como a página responde
Todo controle da página envia da mesma forma: a caixa de busca, o botão Novo, o Editar e o Delete de uma linha e o próprio formulário carregam três campos ocultos, action, crud e, quando faz sentido, key. O host os lê e chama ProcessAction, que responde com o markup a ser trocado.
Uma mensagem enviada pelo socket não carrega nenhum caminho, então ela nunca chega ao roteador e nunca passa pela verificação própria do roteador. Autorizá-la é trabalho da aplicação, e o motor agora entrega a você o que isso exige:
oSession := FHTMXEngine.MessageSession(aConnection, FAuth);
try
if not Assigned(oSession) then
Exit; // a write with nobody behind it is not a write
oPage.ProcessAction(vAction, oParams.Values['key'], oParams, aResponse);
finally
oSession.Free;
end;
A chave que chega do navegador é localizada antes de qualquer gravação ser executada, de modo que uma chave que não pertence a ninguém não grava nada.
Veja as duas versões
Em Demos\60.HTML\01.RunTime\02.AdminCRUD, /customers é o componente e /customers-classic é a página que ele substituiu. Mesmo banco de dados, mesmos dados, mesma aparência. Um deles é quatrocentas linhas mais curto.
Atualização
O componente faz parte do sgcHTML e é aditivo: nada muda em uma página existente até que você solte um no formulário.
Leia também
- Faça uma pergunta ao seu grid Delphi em inglês simples
- Alcance um navegador fechado, a partir do Delphi
- sgcWebSockets 2026.10, tudo o mais nesta versão
Assista ao vídeo
Há um vídeo curto sobre isso no canal da eSeGeCe.
Dúvidas, feedback ou ajuda com a migração? Entre em contato — você receberá uma resposta das pessoas que escreveram o código.
