# Formulários

Formulários que gravam registros, com proteção contra falsificação, filtro de spam e validação.

Um formulário no site grava um registro num recurso. O Nimbly o gera a partir de uma pequena definição em JSON, o protege contra envios falsificados e automatizados, o valida em relação ao recurso e guarda o resultado como qualquer outro registro.

## Um formulário de contato

1. **O recurso** que recebe os envios, `ext/data/leads/.meta`:

```json
{
  "name": {"singular": "Lead", "plural": "Leads"},
  "fields": {
    "name": {"name": "Name", "type": "text", "required": true},
    "email": {"name": "Email", "type": "email", "required": true},
    "message": {"name": "Message", "type": "textarea", "admin_col": false}
  },
  "sort": {"field": "_created", "flags": "numeric", "order": "desc"}
}
```

2. **A definição do formulário**, ao lado da rota que o mostra, `ext/uri/contact/contact.json`:

```json
{
  "name": "contact",
  "resource": "leads",
  "success_message": "Thank you, we will be in touch.",
  "fields": {
    "name": {"type": "text", "name": "Your name", "required": true},
    "email": {"type": "email", "name": "Email address", "required": true},
    "message": {"type": "textarea", "name": "Message"}
  },
  "buttons": [{"type": "submit", "title": "Send"}]
}
```

3. **O formulário na página**, em `ext/uri/contact/main.tpl`:

```html
[#build-form contact#]
```

4. **Abra a única operação de que os visitantes precisam.** A API é fechada para visitantes anônimos. Permita apenas criar leads, com uma rota em `ext/uri/api/v1/leads/index.tpl`:

```html
[#api-allow post leads#]
```

Todo o resto no recurso leads continua protegido. Os envios aparecem no admin em Leads.

## O que o formulário faz por você

- **Proteção contra falsificação.** Cada formulário leva uma chave ligada à sessão do visitante.
- **Filtro de spam.** Um campo honeypot oculto barra bots simples.
- **Validação.** Campos obrigatórios e tipos de campo são verificados no navegador e de novo no servidor, em relação à definição do recurso.
- **Envio sem recarregar a página**, com a mensagem de sucesso no lugar.

## Campos

Os campos do formulário usam os tipos de campo dos recursos: `text`, `textarea`, `email`, `url`, `select`, `upload` e outros. `"help"` acrescenta uma dica abaixo de um campo. Os campos podem ser agrupados lado a lado:

```json
"fields": {
  "_g1": {"type": "group_start", "name": "Name"},
  "first_name": {"type": "text", "name": "First name"},
  "last_name": {"type": "text", "name": "Last name"},
  "_g1e": {"type": "group_end"}
}
```

Para envio de arquivo, use um campo `upload` com `accept`, e indique-o em `"upload_field"` no nível superior da definição.

## Estilo

O formulário recebe as classes `nb-form` e `nb-form-<name>`, e cada invólucro de campo recebe `nb-field` e `nb-form-field-<name>`. Estilize-as em `ext/theme.css`, ou substitua as classes do invólucro por formulário com `[#build-form contact field-wrapper-class="my-2"#]`.

## Depois de um envio

Para enviar uma confirmação ou avisar a equipe, declare um evento no recurso. Uma entrada `job:` coloca o trabalho na fila, para que o visitante nunca espere pelo servidor de e-mail:

```json
"events": {"create": ["job:lead-created"]}
```

Veja [Trabalho em segundo plano](/pt/docs/guides/jobs/) para o handler.

## Seu próprio markup de formulário

O `[#build-form#]` é uma conveniência, não uma obrigação. Um formulário seu, com qualquer markup e qualquer código de frontend, pode enviar para o mesmo endpoint da API. Na stack padrão, `nb.api.post()` envia um registro a partir do Alpine. Para processamento além de guardar um registro, uma rota pode ter os handlers `validate_<name>.inc` e `post_<name>.inc`, que rodam no envio.
