Nuxt
Eine Nuxt-Komponente, die vor der Hydration als einfaches Formular sendet und danach mit $fetch, mit der Formular-ID in der Runtime-Config. Funktioniert mit nuxt generate.
Nuxt rendert das Formular auf dem Server, daher ist das HTML, das im Browser ankommt, bereits ein funktionierendes Formular. Bis die App hydriert, sendet es wie jedes HTML-Formular; danach übernimmt die Komponente und zeigt das Ergebnis direkt an. Auf deinem Server läuft nichts, daher funktioniert es auch als statische Site, gebaut mit nuxt generate.
Um stattdessen aus einer Nuxt-Server-Route mit einem geheimen Schlüssel zu senden, siehe Vue.
Einrichten
Lege die Formular-ID in der Runtime-Config ab
nuxt.config.ts export default defineNuxtConfig({ runtimeConfig: { public: { ikiformFormId: "frm_xxxxxxxxxxxxxxxx", }, }, });Überschreibe sie pro Umgebung mit
NUXT_PUBLIC_IKIFORM_FORM_ID. Mitnuxt generatewird der Wert beim Build fest eingebaut, setze die Variable also in der Build-Umgebung.Füge die Komponente hinzu
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>- Lege sie unter Nuxt 3 in
components/statt inapp/components/ab. ignoreResponseError: trueverhindert, dass$fetchbei4xxwirft, sodass der Fehler-Envelope als Daten zurückkommt. Nur Netzwerkfehler landen incatch.@submit.preventexistiert erst, wenn die App hydriert ist. Davor sendet der Browser anactionund folgt_redirect.
- Lege sie unter Nuxt 3 in
Verwende sie auf einer Seite
app/pages/contact.vue <template> <ContactForm /> </template>
Der Fallback braucht Server-Rendering oder Prerendering. Mit ssr: false ist die Seite leer, bis JavaScript läuft, ohne JavaScript gibt es also kein Formular zum Absenden.
Erlaubte Domains
Liste die Produktion plus die Preview-Hosts deines Deployment-Ziels auf.
| Wo das Formular läuft | Zu Allowed domains hinzufügen |
|---|---|
nuxt dev | localhost. Passt auf http://localhost:3000: Ikiform vergleicht nur den Hostnamen, nie den Port. |
| Deine Domain | example.com, was auch www.example.com abdeckt |
| Vercel | your-project.vercel.app. Preview-URLs wie your-project-git-branch-team.vercel.app passen nicht darauf; füge den exakten Preview-Host hinzu, während du eine Preview testest. |
| Netlify | your-site.netlify.app. Deploy Previews (deploy-preview-12--your-site.netlify.app) und Branch Deploys (branch--your-site.netlify.app) sind keine Subdomains davon, füge also den exakten Preview-Host hinzu, während du eine testest. |
| Cloudflare Pages | your-project.pages.dev. Preview-URLs wie abc123.your-project.pages.dev sind Subdomains davon und passen daher bereits. |
- Füge niemals
vercel.app,netlify.appoderpages.devallein hinzu. Jede Site auf diesem Host würde passen, auch die von anderen Leuten.
Test-Checkliste
- Starte
nuxt devmitlocalhostin den erlaubten Domains und sende ab. Die Dankesnachricht sollte das Formular ersetzen. - Schalte JavaScript in den Dev-Tools deines Browsers aus, lade neu und sende ab. Lokal solltest du auf der Dankesseite von Ikiform landen, auf deiner
https:-Domain auf/thanks. - Sende bei definierten Feldern eine ungültige E-Mail ab und prüfe, dass die Meldung unter dem Feld erscheint.
- Starte
nuxt generate, deploye die Ausgabe und sende vom Preview-Host ab.
Fehlerbehebung
| Was du siehst | Warum | Lösung |
|---|---|---|
FetchError: [POST] "https://ikiform.com/f/...": 422 | ignoreResponseError fehlt, daher wirft $fetch bei Fehlern | Füge ignoreResponseError: true hinzu. |
404 not_found, und die action endet auf /f/undefined | Die Formular-ID war beim Build der Site nicht gesetzt | Setze NUXT_PUBLIC_IKIFORM_FORM_ID in der Build-Umgebung oder den Standardwert in nuxt.config.ts. |
| Ohne JavaScript passiert nichts | Die Seite wird mit ssr: false clientseitig gerendert | Aktiviere Server-Rendering oder prerendere die Seite. |
Einsendungen landen im Spamfilter mit origin_mismatch | Die sendende Seite steht nicht in den erlaubten Domains des Formulars | Füge den Host aus der Tabelle oben hinzu. Mit Reject bekommen dieselben Requests stattdessen 403 origin_not_allowed. |