Nuxt
Um componente Nuxt que envia como um formulário comum antes da hidratação e com $fetch depois, com o id do formulário na runtime config. Funciona com nuxt generate.
O Nuxt renderiza o formulário no servidor, então o HTML que chega ao navegador já é um formulário funcional. Até o app hidratar, ele envia como qualquer formulário HTML; depois disso, o componente assume e mostra o resultado no lugar. Nada roda no seu servidor, então também funciona como site estático gerado com nuxt generate.
Para enviar a partir de uma server route do Nuxt com uma chave secreta, veja Vue.
Configuração
Coloque o id do formulário na runtime config
nuxt.config.ts export default defineNuxtConfig({ runtimeConfig: { public: { ikiformFormId: "frm_xxxxxxxxxxxxxxxx", }, }, });Sobrescreva por ambiente com
NUXT_PUBLIC_IKIFORM_FORM_ID. Comnuxt generate, o valor é fixado no build, então defina a variável no ambiente de build.Adicione o componente
app/components/ContactForm.vue <script setup lang="ts"> type Result = | { ok: true; id: string } | { ok: false; error: { message: string; fields?: Record<string, string[]> } }; const config = useRuntimeConfig(); const endpoint = `https://ikiform.com/f/${config.public.ikiformFormId}`; const status = ref<"idle" | "sending" | "sent" | "error">("idle"); const errors = ref<Record<string, string[]>>({}); const message = ref(""); async function onSubmit(event: Event) { status.value = "sending"; const result = await $fetch<Result>(endpoint, { method: "POST", headers: { Accept: "application/json" }, body: new FormData(event.currentTarget as HTMLFormElement), ignoreResponseError: true, }).catch(() => null); if (result?.ok) { status.value = "sent"; return; } errors.value = result?.error.fields ?? {}; message.value = result?.error.message ?? "Couldn't reach the server. Try again."; status.value = "error"; } </script> <template> <p v-if="status === 'sent'">Thanks, we got it.</p> <form v-else :action="endpoint" method="post" @submit.prevent="onSubmit"> <label> Email <input name="email" type="email" autocomplete="email" required /> </label> <p v-if="errors.email">{{ errors.email[0] }}</p> <label> Message <textarea name="message" rows="5" /> </label> <input type="hidden" name="_redirect" value="https://example.com/thanks" /> <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden /> <p v-if="status === 'error' && !errors.email" role="alert">{{ message }}</p> <button :disabled="status === 'sending'">{{ status === "sending" ? "Sending" : "Send" }}</button> </form> </template>- No Nuxt 3, coloque em
components/em vez deapp/components/. ignoreResponseError: trueimpede que o$fetchlance exceção em4xx, então o envelope de erro volta como dado. Só falhas de rede chegam aocatch.@submit.preventsó existe depois que o app hidrata. Antes disso, o navegador envia para oactione segue o_redirect.
- No Nuxt 3, coloque em
Use em uma página
app/pages/contact.vue <template> <ContactForm /> </template>
O fallback precisa de renderização no servidor ou pré-renderização. Com ssr: false, a página fica vazia até o JavaScript rodar, então não existe formulário para enviar sem ele.
Domínios permitidos
Liste a produção mais os hosts de preview de onde você faz deploy.
| Onde o formulário roda | Adicione em Allowed domains |
|---|---|
nuxt dev | localhost. Ele corresponde a http://localhost:3000: o Ikiform compara só o nome do host, nunca a porta. |
| Seu domínio | example.com, que também cobre www.example.com |
| Vercel | your-project.vercel.app. URLs de preview como your-project-git-branch-team.vercel.app não correspondem a ele; adicione o host exato do preview enquanto testa um. |
| Netlify | your-site.netlify.app. Deploy previews (deploy-preview-12--your-site.netlify.app) e branch deploys (branch--your-site.netlify.app) não são subdomínios dele, então adicione o host exato do preview enquanto testa um. |
| Cloudflare Pages | your-project.pages.dev. URLs de preview como abc123.your-project.pages.dev são subdomínios dele, então já correspondem. |
- Nunca adicione
vercel.app,netlify.appoupages.devsozinhos. Todo site naquele host corresponderia, inclusive os de outras pessoas.
Checklist de teste
- Rode
nuxt devcomlocalhostnos domínios permitidos e envie. A mensagem de agradecimento deve substituir o formulário. - Desative o JavaScript nas ferramentas de desenvolvedor do navegador, recarregue e envie. Você deve chegar à página de agradecimento do Ikiform localmente, ou a
/thanksno seu domíniohttps:. - Envie um e-mail inválido com os campos definidos e confirme que a mensagem aparece abaixo do campo.
- Rode
nuxt generate, faça deploy do resultado e envie a partir do host de preview.
Solução de problemas
| O que você vê | Por quê | Correção |
|---|---|---|
FetchError: [POST] "https://ikiform.com/f/...": 422 | Falta ignoreResponseError, então o $fetch lança exceção em erros | Adicione ignoreResponseError: true. |
404 not_found, e o action termina em /f/undefined | O id do formulário não estava definido quando o site foi gerado | Defina NUXT_PUBLIC_IKIFORM_FORM_ID no ambiente de build, ou o padrão em nuxt.config.ts. |
| Sem JavaScript, nada acontece | A página é renderizada no cliente com ssr: false | Ative a renderização no servidor ou pré-renderize a página. |
Os envios chegam no filtro de spam com origin_mismatch | A página que enviou não está nos domínios permitidos do formulário | Adicione o host da tabela acima. Com Reject escolhido, os mesmos envios recebem 403 origin_not_allowed. |