Capítulo 10
Svelte: loja e formulário
2 min de leitura 432 palavras 1 gravura
Neste capítulo você vai usar uma store simples e um formulário de encomenda fictícia. O projeto-fio é o Ateliê Boa Viagem, ateliê digital fictício em Boa Viagem, Recife.
Seu ponto de partida
Use o exemplo 10-svelte-formulario do pacote anexo e copie inicio/ para uma pasta de prática fora do original. A raiz do exemplo é a referência completa desta etapa.
Use servidor só em 127.0.0.1 quando o README do exemplo pedir HTTP local. Abrir ou testar não publica nada.
Como praticar
Leia → copie ou digite → mude uma coisa → preveja → salve → recarregue → confira. Restaure cada experiência antes da próxima. Faça as atividades antes de abrir as respostas comentadas.

Store para estado compartilhado
Uma store writable permite que partes da UI leiam o mesmo valor. No exemplo compilado, um módulo simula a store.
Faça na sua cópia
Confira o trecho no contexto do exemplo antes de mudar.
export const pedidos = writable(0);
Mude uma coisa e preveja
Incremente pedidos ao enviar o formulário.
Anote o que espera observar antes de salvar e recarregar.
Recarregue e confira
O contador global sobe.
Se não acontecer
Assine/atualize conforme o README do exemplo.
Formulário com bind
bind:value liga campo e variável. Validação mínima evita encomenda vazia.
Faça na sua cópia
Confira o trecho no contexto do exemplo antes de mudar.
<input bind:value={peca} id="peca">
Mude uma coisa e preveja
Exija pelo menos 3 caracteres.
Anote o que espera observar antes de salvar e recarregar.
Recarregue e confira
Nomes curtos não entram na lista.
Se não acontecer
Valide no handler de submit.
Acessibilidade no formulário
Todo campo tem label. Erros são texto, não só cor. Foco permanece compreensível.
Faça na sua cópia
Confira o trecho no contexto do exemplo antes de mudar.
<label for="peca">Peça encomendada</label>
<input id="peca" name="peca">
Mude uma coisa e preveja
Associe um segundo campo observacoes.
Anote o que espera observar antes de salvar e recarregar.
Recarregue e confira
Clicar no rótulo foca o campo.
Se não acontecer
for e id precisam coincidir.
Atividades
Atividade 1
Quando uma store ajuda?
Atividade 2
O que bind:value evita escrever à mão?
Atividade 3
Por que erro não pode ser só cor?
Respostas comentadas
Resposta da atividade 1
Quando várias partes leem/escrevem o mesmo estado.
Resposta da atividade 2
A sincronização manual value + on:input.
Resposta da atividade 3
Quem não distingue cores perde a informação.
O arquivo completo
Referência do exemplo 10-svelte-formulario, reproduzida aqui para que você possa conferir sem sair da página.
index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Svelte formulário — Ateliê Boa Viagem</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<a class="skip" href="#conteudo">Ir para o conteúdo</a>
<header>
<p><strong>Ateliê Boa Viagem</strong></p>
<nav aria-label="Principal"><ul class="nav"><li><a href="index.html" aria-current="page">Início</a></li></ul></nav>
</header>
<main id="conteudo">
<h1>Encomendas</h1>
<p>Pedidos na loja: <strong id="pedidos">0</strong></p>
<form id="form">
<label for="peca">Peça encomendada</label>
<input id="peca" name="peca" required minlength="3">
<label for="obs">Observações</label>
<textarea id="obs" name="obs" rows="3"></textarea>
<p id="erro" role="alert" hidden>Informe pelo menos 3 caracteres.</p>
<p><button type="submit">Registrar</button></p>
</form>
<ul id="lista"></ul>
<script src="store.js"></script>
<script src="app.js"></script>
</main>
<footer><p>Conteúdo fictício. Estudo em 127.0.0.1.</p></footer>
</body>
</html>
app.js
const lista = document.getElementById('lista');
const pedidosEl = document.getElementById('pedidos');
const erro = document.getElementById('erro');
AtelieStore.subscribe((v) => { pedidosEl.textContent = String(v); });
document.getElementById('form').addEventListener('submit', (e) => {
e.preventDefault();
const peca = document.getElementById('peca').value.trim();
if (peca.length < 3) { erro.hidden = false; return; }
erro.hidden = true;
const li = document.createElement('li');
li.textContent = peca;
lista.appendChild(li);
AtelieStore.set(AtelieStore.pedidos + 1);
e.target.reset();
});