Repository navigation
templates
Home > Servir site e arquivos > Templates 🚧
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: básico
Em uma frase: o TRALMustacheEngine monta uma página a partir de um modelo
Mustache e dos seus dados (JSON, TDataSet, listas,
objetos), sem lógica dentro do modelo.
Você vai precisar: o pacote RALModuleWebPackage (paleta RAL - Modules).
Solte um TRALMustacheEngine no formulário (ou crie por código) e ajuste:
| propriedade | |
|---|---|
TemplateRoot |
pasta dos arquivos de modelo; relativa ao executável se não for absoluta. Vazia: só AddTemplate e OnLoadTemplate
|
Extension |
acrescentada ao nome sem extensão (.html por padrão) |
WatchFiles |
True (padrão): relê o arquivo quando a data muda; desligue em produção para poupar a checagem |
Layout |
nome do modelo em que toda página respondida entra, no bloco content
|
Streamed |
envia a página aos poucos enquanto monta, em vez de inteira |
AllowFilters |
liga os filtros {{nome | filtro}} (desligado por padrão) |
OnFilter |
seus próprios filtros |
OnLoadTemplate |
entrega o modelo de qualquer lugar (recurso, banco); roda antes de procurar o arquivo |
Engine.AddTemplate('nome', 'texto') registra um modelo por código e vale mais que o
arquivo. Engine.Reload descarta tudo o que foi compilado.
uses RALTemplate, RALJson;
Motor := TRALMustacheEngine.Create(Self);
Motor.TemplateRoot := 'modelos';
Motor.Layout := 'layout';
Servidor.CreateRoute('clientes', {$IFDEF FPC}@{$ENDIF}Listar);
procedure TForm1.Listar(ARequest: TRALRequest; AResponse: TRALResponse);
var
Dados: TRALJSONObject;
begin
Dados := TRALJSONObject.Create; // ou um TDataSet, um TStringList, um objeto...
try
// ... preenche
Motor.Render(AResponse, 'clientes', [Dados]); // modelos/clientes.html dentro do layout
finally
Dados.Free;
end;
end;Render(AResponse, nome, [dados], status, usarLayout) responde como HTML; o status é
200 e o layout é usado, se houver, a menos que você diga o contrário. Com Streamed,
a resposta sai em pedaços. Para outros destinos: Render(nome, [dados], AStream),
RenderText(nome, [dados]) (texto, sem layout) e RenderSource(texto, [dados])
(sem guardar nada).
Lazarus/FPC: os handlers de evento (
OnFilter,OnLoadTemplate) e de rota levam{$IFDEF FPC}@{$ENDIF}na frente, como em qualquer evento do RAL.
Cada item do array é um contexto; o último é procurado primeiro, depois os anteriores (bom para um item de página por cima de dados comuns).
| dado | como o modelo o vê |
|---|---|
TRALJSON |
objeto = mapa, array = lista; null e false pulam a seção |
TDataSet |
lista de registros, cada um um mapa dos campos. Ponha RALTemplateDB no uses. Anda registro a registro, sem carregar tudo; o dataset fica no fim |
TStrings |
lista das linhas e mapa dos pares Nome=Valor
|
TCollection |
lista dos itens |
| outro objeto | mapa das propriedades published
|
TRALTemplateMap |
junta vários: TRALTemplateMap.Create.Add('titulo', 'Clientes').Add('lista', Query).AddBoolean('admin', True)
|
Os objetos precisam viver até o fim do render. Para um tipo seu, registre uma visão
com RALRegisterTemplateData(MinhaClasse, MinhaVisao).
Olá, {{nome}} escapa o HTML
{{{html}}} ou {{&html}} cru, sem escapar
{{cliente.endereco.cidade}} caminho com ponto
{{#itens}}{{nome}}{{/itens}} seção: repete numa lista, entra num mapa, aparece se verdadeiro
{{^itens}}Nada{{/itens}} invertida: só se vazio, nulo ou falso
{{#tags}}[{{.}}]{{/tags}} o ponto é o item atual
{{! comentário }}
{{> rodape}} parcial (outro modelo, no lugar)
{{=<% %>=}} troca os delimitadoresHerança: o modelo filho preenche os blocos do pai.
{{! base.html }}
<title>{{$titulo}}Site{{/titulo}}</title>
<body>{{$corpo}}{{/corpo}}</body>
{{! pagina.html }}
{{<base}}
{{$titulo}}Clientes{{/titulo}}
{{$corpo}}<h1>{{titulo}}</h1>{{/corpo}}
{{/base}}Parcial dinâmico: {{>*nome}} abre o modelo cujo nome está na variável nome.
Parcial inexistente rende vazio; um modelo pedido por Render que não existe levanta
ERALException. Parciais e pais aninham até 100 níveis (recursão infinita é cortada).
O Layout é um modelo com {{$content}}...{{/content}}: a página responde dentro
dele e pode preencher outros blocos ({{$title}}).
Com AllowFilters := True: {{nome | trim | upper}}, em cadeia, com argumento entre
aspas depois de :.
| filtro | faz |
|---|---|
upper, lower, trim
|
caixa e espaços |
default:"x" |
x se o valor for vazio |
json |
texto como string JSON (use com {{{ }}}) |
url |
percent-encoding |
date:"dd/mm/yyyy" |
data ISO 8601 formatada (sem argumento, a data local) |
number:"0.00" |
número formatado |
Filtros próprios no OnFilter(Sender, AFilter, AArgument, var AValue, var AHandled);
filtro desconhecido deixa o valor como está. Com AllowFilters desligado, a barra faz
parte do nome da variável (e o resultado é vazio).
Para montar HTML por código, a unit RALHtml oferece: RALHtmlEscape (texto entre
tags), RALHtmlAttrEscape (valor de atributo), RALJsEscape (dentro de string
JavaScript) e RALUrlEscape (segmento de URL ou query).
Funções lambda ({{#fn}}) não são executadas; calcule o valor antes e entregue
pronto. Lógica (if, comparações) também não: é da natureza do Mustache.
O modelo é compilado uma vez e guardado; o arquivo só é relido quando a data muda
(WatchFiles). Pode renderizar de várias threads ao mesmo tempo. Um TDataSet grande
usa memória constante, porque cada registro vira uma visão que é liberada em seguida;
com Streamed a página também sai sem ser montada inteira.
-
{{x}}escapa o HTML; só{{{x}}}e{{&x}}deixam passar. Use cru apenas para conteúdo seu. - O nome de um modelo (inclusive o vindo de
{{>*nome}}) nunca sai daTemplateRoot: nomes com..,:ou começando em/são recusados. -
AllowFiltersvem desligado: modelos que você não escreveu não ganham filtros.
Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- JSON-RPC 2.0 🚧
- Servidor MCP (IA) 🚧
- WebSocket 🚧
- Hubs (WebSocket) 🚧
- Swagger e Postman
- Servidor SOAP 🚧
- WS-Security 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar