# Campos e validação

> Defina os campos uma vez e o Ikiform valida cada envio no servidor, com mensagens claras e valores tipados.

Campos são opcionais. Um formulário sem campos aceita quaisquer dados que o seu formulário enviar. Depois que você publica os campos, o Ikiform valida cada envio contra eles no servidor, rejeita dados ruins com mensagens claras e armazena valores limpos e tipados.

## Definindo campos

Abra um formulário no painel e vá em **Fields**. Adicione campos no editor visual ou edite a definição JSON diretamente. O `id` de cada campo é o `name` do input que o seu formulário precisa enviar.

`Definição do formulário`:

```json
{
  "version": 1,
  "title": "Contact",
  "fields": [
    { "id": "name", "type": "text", "label": "Name", "required": true, "validation": { "max_length": 120 } },
    { "id": "email", "type": "email", "label": "Email", "required": true },
    {
      "id": "topic",
      "type": "select",
      "label": "Topic",
      "options": [
        { "value": "sales", "label": "Sales" },
        { "value": "support", "label": "Support" }
      ]
    },
    { "id": "message", "type": "textarea", "label": "Message", "validation": { "min_length": 10 } }
  ],
  "settings": { "submit_label": "Send", "success_message": "Thanks, we'll reply within a day." }
}
```

### A definição

| Chave | Obrigatório | Regras |
| --- | --- | --- |
| `version` | Sim | Sempre `1` |
| `title` | Sim | De 1 a 200 caracteres |
| `description` | Não | Até 2.000 caracteres |
| `fields` | Sim | De 1 a 100 campos com ids únicos, no máximo 2.000 opções no total |
| `settings.submit_label` | Não | De 1 a 100 caracteres, usado por renderizadores como o [componente shadcn/ui](https://ikiform.com/pt-br/docs/shadcn.md) |
| `settings.success_message` | Não | De 1 a 1.000 caracteres |
| `settings.redirect_url` | Não | Uma URL `http:` ou `https:` com até 2.048 caracteres |
| `$schema` | Não | Qualquer string com até 200 caracteres, ignorada |

Chaves desconhecidas são recusadas, no nível superior e em cada campo, então um erro de digitação como `requried` aparece como erro quando você salva.

### Chaves de todo campo

| Chave | Obrigatório | Regras |
| --- | --- | --- |
| `id` | Sim | snake_case em minúsculas, começando com uma letra, com no máximo 64 caracteres, por exemplo `team_size` |
| `type` | Sim | Um dos 12 tipos abaixo |
| `label` | Sim | De 1 a 200 caracteres. Usado nas páginas de erro e nos e-mails de notificação |
| `required` | Não | `true` faz um valor vazio ser erro |
| `placeholder` | Não | Até 200 caracteres |
| `help_text` | Não | Até 1.000 caracteres |

## Playground

O playground interativo desta página permite editar uma definição de formulário e um payload JSON de exemplo. Ele roda o validador real do Ikiform no navegador e mostra a resposta `201` ou `422` exata que o servidor retornaria, os valores armazenados após a conversão e o markup HTML gerado para o formulário.

## Tipos de campo

| Tipo | Armazenado como | Aceita |
| --- | --- | --- |
| `text` | string | Qualquer texto de uma linha |
| `textarea` | string | Texto com várias linhas |
| `email` | string, domínio em minúsculas | Um endereço de e-mail |
| `number` | number | Números, ou strings numéricas vindas de formulários HTML |
| `select` | string | O valor de uma opção da lista |
| `radio` | string | O valor de uma opção da lista |
| `multi_select` | string[] | Valores de opções da lista, sem duplicados |
| `checkbox` | boolean | `on`, `true`, `1`, `yes`, ou nada |
| `date` | string, `YYYY-MM-DD` | Uma data real do calendário |
| `url` | string, normalizada | Um endereço web, com `https://` adicionado quando falta |
| `phone` | string | Dígitos, espaços, `+ ( ) . -` |
| `rating` | integer | Um número inteiro de 1 a `max` |

### text

| validation | Valores | Padrão |
| --- | --- | --- |
| `min_length` | De 0 a 10.000 | Nenhum |
| `max_length` | De 1 a 10.000, ou no máximo 256 com um pattern | 1.000, ou 256 com um pattern |
| `pattern` | Uma expressão regular com até 200 caracteres, comparada com o valor inteiro | Nenhum |
| `pattern_message` | De 1 a 200 caracteres | `Invalid format` |

Os patterns rodam com a flag `u` e precisam corresponder ao valor inteiro. Quando você salva, o Ikiform recusa patterns que poderiam causar backtracking catastrófico: backreferences, grupos repetidos que contêm repetições ou alternativas (`(a+)+`, `(a|b)*`) e repetições aninhadas demais.

### textarea

| Chave | Valores | Padrão |
| --- | --- | --- |
| `validation.min_length` | De 0 a 16.000 | Nenhum |
| `validation.max_length` | De 1 a 16.000 | 10,000 |
| `rows` | De 1 a 50, uma dica de exibição para renderizadores | Nenhum |

### email

| validation | Valores | Padrão |
| --- | --- | --- |
| `allowed_domains` | De 1 a 100 domínios como `example.com`, comparados exatamente | Qualquer domínio |

Endereços com mais de 254 caracteres são recusados. A parte do domínio é armazenada em minúsculas; a parte antes do `@` é mantida como foi enviada.

### number

| validation | Valores | Padrão |
| --- | --- | --- |
| `min` | Qualquer número | Nenhum |
| `max` | Qualquer número, no mínimo `min` | Nenhum |
| `integer` | `true` para recusar decimais | `false` |

### select, radio e multi_select

| Chave | Valores | Padrão |
| --- | --- | --- |
| `options` | De 1 a 500 objetos `{ "value", "label" }` com valores únicos, cada um com 1 a 200 caracteres | Obrigatório |
| `validation.min_items` | Só `multi_select`, de 0 a 500 | 0, ou 1 quando obrigatório |
| `validation.max_items` | Só `multi_select`, de 1 a 500 | O número de opções |

Só valores da lista são aceitos. `select` e `radio` aceitam um valor; envie `multi_select` como nomes repetidos, `name[]` ou um array JSON.

### checkbox

Sem chaves extras. Um checkbox ausente é `false`. `required: true` significa que ele precisa estar marcado, o que serve para caixas de consentimento. Valores diferentes de `on`, `true`, `1`, `yes`, `off`, `false`, `0`, `no` ou vazio são recusados.

### date

| validation | Valores | Padrão |
| --- | --- | --- |
| `min` | Uma data `YYYY-MM-DD` | Nenhum |
| `max` | Uma data `YYYY-MM-DD`, igual ou posterior a `min` | Nenhum |

### url

| validation | Valores | Padrão |
| --- | --- | --- |
| `https_only` | `true` para recusar `http:` | `false` |
| `max_length` | De 1 a 4.096 | 2.048 |

Só URLs `http:` e `https:` com um nome de host com ponto e sem usuário ou senha são aceitas. O valor armazenado é a URL normalizada.

### phone

| validation | Valores | Padrão |
| --- | --- | --- |
| `e164` | `true` para exigir o formato internacional, armazenado sem separadores | `false` |

Sem `e164`, um telefone precisa ter de 6 a 15 dígitos e é armazenado como foi enviado. Com ele, `+1 (415) 555-0123` é armazenado como `+14155550123`.

### rating

| validation | Valores | Padrão |
| --- | --- | --- |
| `max` | De 2 a 10 | 5 |

## Conversão de tipos

Formulários HTML enviam tudo como texto. O Ikiform converte cada valor para o tipo que o campo declara antes de armazenar. Com `name` como texto, `email`, `guests` como número, `newsletter` como checkbox, `site` como URL e `phone` como telefone:

`Enviado, urlencoded`:

```text
name=++Ada+Lovelace++&email=Ada@Example.COM&guests=3&newsletter=on&site=example.com&phone=%2B1%20415%20555%200123
```

`Armazenado, com phone em e164`:

```json
{
  "name": "Ada Lovelace",
  "email": "Ada@example.com",
  "guests": 3,
  "newsletter": true,
  "site": "https://example.com/",
  "phone": "+14155550123"
}
```

- Os valores passam por trim. Uma string vazia conta como ausente.
- Um campo que espera um valor recusa um array com mais de um item.
- Números aceitam notação decimal simples e exponencial com até 64 caracteres, como `3`, `-2.5` ou `1e3`.

## Erros de validação

Um envio que falha na validação é rejeitado com `422 validation_failed` e nada é armazenado. `error.fields` associa cada id de campo às suas mensagens. Envios pelo navegador veem as mesmas mensagens em uma página de erro hospedada, identificadas pelos rótulos dos seus campos.

`422 Unprocessable Content`:

```json
{
  "ok": false,
  "error": {
    "code": "validation_failed",
    "message": "Some fields are invalid.",
    "fields": {
      "email": ["Enter a valid email address"],
      "website": ["Unknown field \"website\""]
    }
  },
  "request_id": "req_01k7v2c9t3e8m5q4x6z0a1b2c3"
}
```

### Campos desconhecidos

Com campos definidos, qualquer campo que não está na definição é rejeitado como `Unknown field "name"`. Campos reservados que começam com `_`, o honeypot e `cf-turnstile-response` não contam. Sem definição, quaisquer nomes de campo são aceitos.

### Mensagens

| Problema | Mensagem |
| --- | --- |
| Valor obrigatório ausente | `This field is required` |
| Checkbox obrigatório desmarcado | `This box must be checked` |
| Curto ou longo demais | `Must be at least 10 characters`, `Must be at most 120 characters` |
| Pattern não corresponde | O seu `pattern_message`, ou `Invalid format` |
| E-mail | `Enter a valid email address`, `Email must be at one of: example.com` |
| Número | `Enter a number`, `Enter a whole number`, `Must be at least 1` |
| Opções | `Choose one of the listed options`, `Choose at least 2 options`, `Choose at most 3 options` |
| Data | `Enter a valid date (YYYY-MM-DD)`, `Must be on or after 2026-01-01` |
| URL | `Enter a valid URL`, `Enter a valid https:// URL` |
| Telefone | `Enter a valid phone number`, `Use international format, e.g. +14155550123` |
| Avaliação | `Choose a rating`, `Rating must be at most 5` |

## Validando no navegador

O `validate` do SDK espelha as regras e mensagens do servidor para os 12 tipos de campo, então você pode mostrar erros antes de enviar. O servidor continua sendo a fonte da verdade. Veja [validate](https://ikiform.com/pt-br/docs/sdk.md#validate).
