Become a member!

Construindo Aplicações Web Delphi em Minutos com DMVCFramework e TemplatePro

  • 👉 This article is available in english too.
  • 👉 Este artículo también está disponible en español.
  • 👉 Questo articolo è disponibile anche in italiano.
  • 👉 Este artigo também está disponível em português do Brasil.

No acelerado mundo do desenvolvimento web, velocidade e eficiência não são apenas vantagens—são necessidades. Embora a indústria frequentemente gravite em direção a frameworks JavaScript complexos e cadeias de ferramentas intrincadas, o DMVCFramework se destaca como o projeto Delphi mais popular no GitHub por uma razão convincente: ele entrega aplicações web de nível empresarial com simplicidade e velocidade sem precedentes.

Combinado com o poderoso motor de templates do TemplatePro e aprimorado por ferramentas modernas como WebStencils, este ecossistema representa uma mudança de paradigma em como aplicações web podem ser construídas. Vamos explorar como essas tecnologias permitem que desenvolvedores criem aplicações web sofisticadas em minutos, não em meses.

O Trio Poderoso: DMVCFramework, TemplatePro e WebStencils

DMVCFramework: A Base do Desenvolvimento Web Rápido

DMVCFramework é um framework popular e poderoso para WEB API em Delphi que suporta o desenvolvimento de APIs RESTful e JSON-RPC. O que o diferencia é sua notável capacidade de transformar tarefas complexas de desenvolvimento web em operações simples e intuitivas.

Aqui está o que torna o DMVCFramework excepcional:

Estabilidade Pronta para Produção: Usado por projetos pequenos/médios/grandes desde 2010, o DMVCFramework provou seu valor em ambientes de alto tráfego. Algumas das APIs WEB Delphi (RESTful ou JSONRPC) com maior tráfego são alimentadas pelo DMVCFramework.

Desenvolvimento Instantâneo: Você pode criar um servidor RESTful completo em alguns cliques. O assistente integrado torna a criação de projetos quase instantânea.

Implantação Flexível: Seja um servidor standalone, módulo Apache ou extensão ISAPI, o DMVCFramework se adapta às suas necessidades de infraestrutura.

Ecossistema Rico: Com mais de 100 exemplos e documentação abrangente, os desenvolvedores podem se tornar produtivos imediatamente.

TemplatePro: Templates Modernos Simplificados

TemplatePro é um motor de templates moderno e versátil projetado para simplificar a geração dinâmica de HTML, conteúdo de email e arquivos de texto. Com sintaxe inspirada em sistemas populares como Jinja e Smarty, ele fornece recursos poderosos incluindo blocos condicionais, loops, herança de templates e suporte a dados JSON.

Principais Recursos:

  • Sintaxe Intuitiva: Usa a notação familiar {{}} para expressões e lógica
  • Herança de Templates: Construa layouts e componentes reutilizáveis
  • Filtros Personalizados: Estenda a funcionalidade com transformações de dados específicas do domínio
  • Integração JSON: Manipule dados de API e objetos complexos de forma transparente
  • Performance: Templates compilados garantem execução rápida

Documentação Oficial do TemplatePro está disponível aqui

WebStencils: O Motor de Templates do RAD Studio

WebStencils é o motor de templates nativo do RAD Studio 12.2 que fornece capacidades de script do lado do servidor para estender aplicações WebBroker e RAD Server. WebStencils representa o reconhecimento da Embarcadero da importância de motores de templates modernos no desenvolvimento web.

Ambos os motores suportam lógica condicional, loops, herança de templates e mecanismos de inclusão. No entanto, TemplatePro fornece alguns recursos únicos como filtros personalizados, manipulação nativa de JSON e compilação opcional. O objetivo principal do WebStencils é estender significativamente as tecnologias web existentes no RAD Studio, transformando qualquer motor de Web Service em uma ferramenta abrangente para Web Site e Web Service.

Se você está interessado no motor WebStencils, recomendo fortemente o Guia Gratuito WebStencils and HTMX: Free Guide to Fast Web Development do meu amigo Antonio Zapater.

Início Rápido: Do Download à Aplicação Web Funcionando em 2 Minutos

A beleza do DMVCFramework e TemplatePro está em sua usabilidade imediata. Esqueça procedimentos de configuração complexos—você pode ter uma aplicação web totalmente funcional rodando em menos de 2 minutos.

Passo 1: Baixar e Executar

Simplesmente baixe o projeto quickstart e você está pronto para começar:

  • Baixe o arquivo zip QuickStart
  • Descompacte-o em uma pasta de sua preferência
  • Abra o projeto dmvcframework_templatepro_htmx_quickstart.dproj no Delphi e pressione F9
  • É isso! Seu servidor web está rodando em localhost:8080

A partir de agora você pode renomear arquivos e adicionar as funcionalidades que seu projeto requer.

O projeto quickstart inclui uma aplicação web completa com:

  • Servidor DMVCFramework pré-configurado pronto para rodar
  • Templates TemplatePro já configurados
  • Dados de exemplo e controllers demonstrando melhores práticas
  • Interface web responsiva usando Bootstrap
  • Exemplos funcionais de todos os principais recursos

Passo 2: Explorar o Que Já Está Construído

Abra o projeto e você encontrará um sistema de gerenciamento de clientes totalmente funcional:

// ControllerU.pas - Already implemented!
unit ControllerU;

interface

uses
  MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections;

type
  [MVCPath]
  TMyController = class(TMVCController)
  public
    [MVCPath]
    [MVCHTTPMethod([httpGET])]
    [MVCProduces(TMVCMediaType.TEXT_HTML)]
    function Index: String;

    [MVCPath('/reversedstrings')]
    [MVCHTTPMethod([httpGET])]
    [MVCProduces(TMVCMediaType.TEXT_PLAIN)]
    function GetReversedString(const [MVCFromQueryString('value','')] Value: String): String;

  end;

implementation

uses
  System.StrUtils, System.SysUtils, MVCFramework.Logger;


function TMyController.Index: String;
begin
  Result := RenderView('index');
end;

function TMyController.GetReversedString(const Value: String): String;
begin
  ViewData['reversed_string'] := System.StrUtils.ReverseString(Value.Trim);
  Result := RenderView('partials/reversed');
end;

end.

Passo 3: Ver TemplatePro em Ação

O quickstart inclui templates funcionais que você pode examinar e modificar:

templates/index.html (incluído no quickstart):

{{extends "_layout.html"}}

{{block "body"}}

<div class="row">
    <div class="col">
        <div class="text-center mt-5">
            <h1>DMVCFramework + TemplatePro + HTMX</h1>
            <p class="lead">A complete project boilerplate built with Bootstrap</p>
            <p>Bootstrap v5.3.3</p>
        </div>
    </div>
</div>

<div class="row mt-5">
    <div class="col col-3 offset-3">
        <div class="mb-3">
            <input type="text" name="value" class="form-control" id="exampleFormControlInput1"
              placeholder="Write something here" value="Hello World">
        </div>
    </div>
    <div class="col col-2">
        <button type="button" hx-get="/reversedstrings" hx-include='input' hx-target="#result"
          class="btn btn-primary">Reverse it!</button>
    </div>
</div>
<div class="row">
    <div class="col col-5 offset-3">
        <div id="result" class="alert alert-primary" role="alert">
            {{include "partials/reversed.html"}}
        </div>
    </div>
</div>

{{endblock}}

Passo 4: Personalização Instantânea

Quer ver suas mudanças imediatamente? O quickstart foi projetado para feedback instantâneo:

  1. Modifique um template - Edite templates/index.html
  2. Atualize o navegador - Veja as mudanças imediatamente (nenhuma compilação necessária para templates!)
  3. Crie novos endpoints - Siga os padrões de controller existentes

templates/_layout.hmtl (também incluído):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="description" content="A simple DMVCFramework + TemplatePro + HTMX Template for new projects.">
    <meta name="author" content="Daniele Teti">
    <title>DMVCFramework TemplatePro HTMX Quick Start</title>
    <!-- Latest compiled and minified CSS -->
    <script src="/assets/js/htmx.min.js"></script>
    <link href="/assets/bootstrap-5.3.3/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
    <link rel="stylesheet" href="/assets/css/style.css"/>
    <link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
    <link rel="manifest" href="/assets/site.webmanifest" />
</head>
<body>
        <!-- Responsive navbar-->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container">
                <a class="navbar-brand" href="#">Start Bootstrap</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
                  data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                  aria-expanded="false" aria-label="Toggle navigation">
                  <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" id="navbarDropdown" href="#"
                              role="button" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
                            <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li><hr class="dropdown-divider" /></li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
<div class="container">
    {{block "body"}}{{endblock}}
</div>
<!-- Bootstrap core JS-->
<script src="/assets/bootstrap-5.3.3/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<!-- Core theme JS-->
<script src="/assets/js/scripts.js"></script>
</body>
</html>

Agora é hora de outra foto completamente não relacionada…

Recursos Avançados do TemplatePro em Ação

Trabalhando com Dados JSON

TemplatePro se destaca ao lidar com dados JSON de APIs:

function TMyController.GetCustomers: String;
begin
  //Let's create a dataset containing 15 random people we consider as customers.
  //This dataset is generated by the "Delphi Fake Data Utils" project available here https://github.com/danieleteti/delphi_fake_data_utils
  var lDS := ToFree<TDataSet>(GetPeople(15));
  var lJSON := ToFree<TJSONObject>(TJSONObject.Create);

  //calculate customers avg age
  lDS.First;
  var lAgeCumulative := 0;
  _.ForEachRecord(lDS,
    procedure(const DS: TDataSet)
    begin
      lAgeCumulative := lAgeCumulative + YearsBetween(Now, lDS.FieldByName('dob').AsDateTime);
    end);
  var lAvgAge := lAgeCumulative / lDS.RecordCount;
  lDS.First;
  // end - stats

  lJSON.A['customers'] := lDS.AsJDOJSONArray();
  lJSON.F['avg_age'] := lAvgAge;
  ViewData['data'] := lJSON;
  Result := RenderView('index');
end;

Template de Diretório de Clientes (customers.html):

{{extends "_layout.html"}}

{{block "body"}}

       <h2 class="mb-4">Customers Directory</h2>

        <!-- TemplatePro Template for Dataset Table -->
        {{if data.customers}}
            <div class="table-container">
                <table class="table table-striped table-hover mb-0">
                    <thead>
                        <tr>
                            <th scope="col">#</th>
                            <th scope="col">Code</th>
                            <th scope="col">First Name</th>
                            <th scope="col">Last Name</th>
                            <th scope="col">Country</th>
                            <th scope="col">Date of Birth</th>
                            <th scope="col">Age</th>
                        </tr>
                    </thead>
                    <tbody>
                        {{for customer in data.customers}}
                        <tr {{if customer.@@odd}}class="table-light"{{endif}}>
                            <th scope="row">{{:customer.@@index}}</th>
                            <td>
                                <span class="badge bg-secondary">{{:customer.code}}</span>
                            </td>
                            <td>{{:customer.first_name|capitalize}}</td>
                            <td>{{:customer.last_name|uppercase}}</td>
                            <td>
                                <span class="badge bg-primary badge-country">{{:customer.country|uppercase}}</span>
                            </td>
                            <td>{{:customer.dob}}</td>
                            <td>
                                {{if customer.dob}}
                                    <small class="text-muted">
                                        <!-- Calculate age - you'd implement this as a custom filter -->
                                        {{:customer.dob|age}} years
                                    </small>
                                {{else}}
                                    <small class="text-muted">N/A</small>
                                {{endif}}
                            </td>
                        </tr>
                        {{endfor}}
                    </tbody>
                </table>
            </div>

            <!-- Dataset Statistics -->
            <div class="row mt-4">
                 <div class="col-md-4">
                    <div class="card text-center">
                        <div class="card-body">
                            <h5 class="card-title">{{:data.customers|count}}</h5>
                            <p class="card-text">Total Customers</p>
                        </div>
                    </div>
                </div>
                <div class="offset-md-4 col-md-4">
                    <div class="card text-center">
                        <div class="card-body">
                            <h5 class="card-title">{{:data.avg_age|round,-2}} years</h5>
                            <p class="card-text">Average Age</p>
                        </div>
                    </div>
                </div>
            </div>

        {{else}}
            <!-- Empty State -->
            <div class="alert alert-info text-center" role="alert">
                <h4 class="alert-heading">No Data Available</h4>
                <p>The employee dataset is empty or not loaded.</p>
                <hr>
                <p class="mb-0">Please check your data source and try again.</p>
            </div>
        {{endif}}

        <!-- Action Buttons -->
        <div class="d-flex justify-content-between mt-4">
            <button class="btn btn-outline-secondary" onclick="window.print()">
                Print Table
            </button>
            <div>
                <button class="btn btn-success me-2" onclick="exportToCSV()">
                    Export CSV
                </button>
                <button class="btn btn-primary" onclick="addEmployee()">
                    Add Employee
                </button>
            </div>
        </div>
    </div>

    <script>
        function exportToCSV() {
            // CSV export functionality
            alert('CSV export would be implemented here');
        }

        function addEmployee() {
            // Add employee functionality
            alert('Add employee form would open here');
        }
    </script>

{{endblock}}

Filtros Personalizados para Lógica de Domínio

Crie filtros especializados para seu domínio de negócios:

// Custom filter for "age" expressed as in "I'm x years old"
function Age(const Value: TValue; const Parameters: TArray<TFilterParameter>): TValue;
begin
  //DOB is a string formatted as yyyy-mm-dd
  Result := YearsBetween(Now, ISODateToDate(Value.AsString));
end;

// Register filters
procedure TemplateProContextConfigure;
begin
  TTProConfiguration.OnContextConfiguration := procedure(const CompiledTemplate: ITProCompiledTemplate)
  begin
    // These filters will be available to the TemplatePro views as if they were the standard ones
    CompiledTemplate.AddFilter('age', Age);
  end;
end;

Use nos templates:

{{if customer.dob}}
    <small class="text-muted">
        <!-- Calculate age - you'd implement this as a custom filter -->
        {{:customer.dob|age}} years
    </small>
{{else}}
    <small class="text-muted">N/A</small>
{{endif}}

Aqui está a página de exemplo resultante.

Funções de Template para Lógica Complexa

Funções fornecem ainda mais poder e podem ser usadas para implementar lógica complexa.

Integração com HTMX

Páginas HTMX podem se beneficiar da geração de código do lado do servidor e se conectar a servidores REST em relação às atualizações de conteúdo. As tecnologias web Delphi podem oferecer geração de páginas e APIs REST em um nível de altíssima qualidade.

<!-- HTMX-powered dynamic content -->
<div id="customer-list">
    {{include "partials/customer-list.html"}}
</div>

<button hx-get="/api/customers"
        hx-target="#customer-list"
        hx-swap="innerHTML">
    Refresh Customers
</button>

<form hx-post="/api/customers"
      hx-target="#customer-list"
      hx-swap="innerHTML">
    <input name="name" placeholder="Customer Name" required>
    <input name="email" placeholder="Email" required>
    <button type="submit">Add Customer</button>
</form>

TemplatePro suporta Recursos Empresariais como:

  • Templates Compilados para máximo desempenho e menor carga de CPU
  • Autenticação e Autorização templates podem ter acesso às funções do usuário.
  • Tratamento de Erros em caso de erros não tratados, o tratamento de erros padrão é acionado (verifique o exemplo \samples\custom_exception_handling_using_controller)

Recursos de Aprendizado e Próximos Passos

Começando Imediatamente

A maneira mais rápida de começar é usar o assistente DMVCFramework na IDE Delphi. DMVCFramework permite criar servidores RESTful poderosos sem esforço. Você pode criar um servidor RESTful completo em alguns cliques.

Comunidade e Suporte

Sobre WebStencils

Para cobertura abrangente do WebStencils e integração HTMX, recomendamos fortemente o download do White Paper gratuito por Antonio Zapater disponível no blog da Embarcadero. Este guia fornece cobertura aprofundada de:

  • Técnicas avançadas de script WebStencils
  • Padrões de integração HTMX
  • Estratégias de implantação empresarial
  • Otimização de desempenho
  • Melhores práticas de segurança

Conclusão

A combinação de DMVCFramework e TemplatePro (ou WebStencils) representa um paradigma poderoso para desenvolvimento web rápido. Enquanto outros frameworks requerem processos de build complexos, conhecimento extenso de JavaScript e procedimentos de implantação intrincados, esta stack baseada em Delphi entrega:

Velocidade: Do conceito à produção em minutos, não semanas Simplicidade: Sintaxe intuitiva que os desenvolvedores podem dominar rapidamente Poder: Recursos de nível empresarial sem complexidade de nível empresarial Flexibilidade: Implante em qualquer lugar, integre com qualquer coisa Estabilidade: Testado em batalha em ambientes de produção em todo o mundo

Como revelado por uma análise da Embarcadero, DMVCFramework é o projeto Delphi mais popular para WebAPI e WebApp no GitHub desde 2017, e sua integração com motores de templates modernos como TemplatePro e WebStencils apenas fortalece sua posição como a solução ideal para desenvolvimento web rápido.

Seja construindo ferramentas internas, aplicações voltadas para o cliente ou APIs empresariais, esta stack fornece o equilíbrio perfeito de produtividade e profissionalismo. A curva de aprendizado é suave, a documentação é abrangente e a comunidade é solidária.

Para desenvolvedores cansados de cadeias de ferramentas complexas e soluções super-engenhadas, DMVCFramework com TemplatePro oferece um retorno revigorante à simplicidade sem sacrificar a capacidade. Em um mundo onde o desenvolvimento web muitas vezes parece desnecessariamente complicado, essas ferramentas provam que às vezes a melhor solução também é a mais simples.

Pronto para experimentar a velocidade e simplicidade por si mesmo? Comece com o assistente DMVCFramework, explore os exemplos, e mergulhe nos recursos gratuitos disponíveis. Sua próxima aplicação web está a apenas alguns minutos de distância.

Comments

comments powered by Disqus