Dica 05 - htmx simples
Versões usadas no vídeo: não usa Django; htmx 1.8.4, Tailwind CSS 3 (Play CDN) e Python 3.10.6 (só para o http.server).
Github: https://github.com/rg3915/dicas-de-django (branch aula05)
Playlist sobre htmx: https://www.youtube.com/watch?v=W4AKpCh1Sj0&list=PLsGCdfxkV9upBW0CS7CyvkP64GoxvTDDd
Nesta dica vamos ver, de uma forma bem simples, como funciona o htmx. Vamos fazer uma tabela com um campo de texto e um botão Adicionar: a cada clique, o htmx busca um pedaço de HTML (um "componente") e acrescenta uma nova linha na tabela, sem escrever nenhuma linha de JavaScript.
Repare que o htmx não tem nada a ver com o Django: ele só faz uma requisição e coloca no DOM o HTML que voltou. Aqui o HTML vem de um arquivo estático servido pelo http.server; mais adiante no projeto, ele virá de uma view do Django.
Criando a issue e a branch
Com o script da dica 01:
python cli/create_issue.py \
--title='htmx simples - Frontend' \
--body='g ch -b aula05
https://htmx.org/' \
--labels='frontend'
Successfully created Issue "htmx simples - Frontend"
A issue criada foi a #96. Então criamos a branch:
git checkout -b aula05
Estrutura e servidor
São dois arquivos: a página (index.html) e o componente que será inserido nela (component.html). Suba o servidor na raiz do projeto, como na dica do http.server:
mkdir -p src/pages/htmx
touch src/pages/htmx/index.html
touch src/pages/htmx/component.html
python -m http.server 8000
A página index.html
A página usa o Tailwind via CDN (como na dica anterior) para estilizar a tabela, o campo e o botão, e carrega o htmx também via CDN:
<!-- htmx -->
<script src="https://unpkg.com/htmx.org@1.8.4"></script>
A tabela tem um <tbody id="tbody"> com uma linha (tr) contendo um input. O botão Adicionar recebe três atributos do htmx:
hx-get="/src/pages/htmx/component.html": ao clicar, o htmx faz umGETnessa URL. É o caminho do arquivo a partir da raiz onde ohttp.serverestá rodando.hx-target="#tbody": o HTML que voltar vai para o elemento comid="tbody".hx-swap="beforeend": o HTML é inserido no fim do conteúdo do alvo, ou seja, como uma nova linha depois das que já existem. (O padrão,innerHTML, substituiria todo o conteúdo dotbody.)
Os trechos principais (o código completo está no link logo abaixo):
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- ... -->
<title>htmx</title>
<!-- TailwindCSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- htmx -->
<script src="https://unpkg.com/htmx.org@1.8.4"></script>
</head>
<body>
<div class="flex flex-col sm:w-1/2">
<!-- ... -->
<table class="min-w-full">
<!-- ... -->
<tbody id="tbody">
<tr class="border-b">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<div class="mb-3 xl:w-96">
<input
type="text"
class="
<!-- ... -->
"/>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<!-- ... -->
<div class="flex space-x-2 justify-center">
<button
type="button"
class="
<!-- ... -->
"
hx-get="/src/pages/htmx/component.html"
hx-target="#tbody"
hx-swap="beforeend"
>
Adicionar
</button>
</div>
</div>
</body>
</html>
Código completo: src/pages/htmx/index.html
O componente component.html
O componente é só uma linha da tabela com o input, igual à primeira linha do tbody. Ele não tem <html>, <head> nem <body>, porque é um pedaço de HTML para ser encaixado na página:
<!-- component.html -->
<tr class="border-b">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<div class="mb-3 xl:w-96">
<input
type="text"
class="
form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700
focus:bg-white
focus:border-blue-600
focus:outline-none
"/>
</div>
</td>
</tr>
Resultado
Abra http://localhost:8000/src/pages/htmx/. A tabela aparece com o cabeçalho Nome, um campo de texto e o botão azul ADICIONAR (o Tailwind deixa o texto em maiúsculas com a classe uppercase). A cada clique no botão, o htmx busca o component.html e acrescenta mais um campo na tabela. No terminal do http.server aparece um GET /src/pages/htmx/component.html por clique.
Tudo isso é só front-end: quando o botão faz o GET naquela URL, o htmx pega o conteúdo do HTML retornado e o coloca dentro do tbody, no final.
Fechando a issue
O vídeo termina com o exemplo funcionando. No repositório, o commit é htmx simples - Frontend. close #96, na branch aula05:
git add .
git commit -m 'htmx simples - Frontend. close #96'
git push
Conclusão
Com três atributos (hx-get, hx-target e hx-swap), o htmx busca HTML no servidor e o insere na página. Isso é uma pequena amostra; para entender todos os atributos, veja a playlist sobre htmx indicada no início.