ID formulir

SvelteKit

Halaman SvelteKit prerender yang formulirnya mengirim langsung ke Ikiform, ditingkatkan dengan fetch begitu JavaScript dimuat. Berfungsi dengan adapter-static.

Halaman ini tidak butuh server: action formulir adalah endpoint Ikiform Anda, jadi berfungsi di adapter-static dan host statis mana pun. Tanpa JavaScript, formulir mengirim dan redirect seperti HTML biasa; dengan JavaScript, formulir mengirim dengan fetch dan menampilkan hasilnya di tempat. Untuk mengirim lewat form action dengan secret key, lihat Svelte.

Kenapa tidak memakai use:enhance

use:enhance milik SvelteKit hanya berfungsi dengan formulir method="POST" yang mengarah ke action yang didefinisikan di file +page.server.js. Ikiform adalah URL eksternal, jadi halaman ini memakai handler onsubmit kecil sebagai gantinya. Progressive enhancement-nya sama: formulir berfungsi lebih dulu, skrip menyempurnakannya.

Penyiapan

  1. Tambahkan environment variable publik

    .env
    PUBLIC_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxx
    PUBLIC_SITE_URL=https://example.com

    PUBLIC_SITE_URL dipakai untuk redirect tanpa JavaScript. Saat prerendering, page.url.origin bernilai http://sveltekit-prerender, bukan domain Anda, jadi redirect tidak bisa dibuat darinya.

  2. Prerender halamannya

    src/routes/contact/+page.js
    export const prerender = true;
  3. Tambahkan formulir

    src/routes/contact/+page.svelte
    <script>
      import { PUBLIC_IKIFORM_FORM_ID, PUBLIC_SITE_URL } from "$env/static/public";
    
      const endpoint = `https://ikiform.com/f/${PUBLIC_IKIFORM_FORM_ID}`;
    
      let status = $state("idle");
      let errors = $state({});
      let message = $state("");
    
      async function onsubmit(event) {
        event.preventDefault();
        status = "sending";
        try {
          const response = await fetch(endpoint, {
            method: "POST",
            headers: { Accept: "application/json" },
            body: new FormData(event.currentTarget),
          });
          const result = await response.json();
          if (result.ok) {
            status = "sent";
            return;
          }
          errors = result.error.fields ?? {};
          message = result.error.message;
        } catch {
          message = "Couldn't reach the server. Try again.";
        }
        status = "error";
      }
    </script>
    
    {#if status === "sent"}
      <p>Thanks, we got it.</p>
    {:else}
      <form action={endpoint} method="POST" {onsubmit}>
        <label>
          Email
          <input name="email" type="email" autocomplete="email" required aria-invalid={errors.email ? "true" : undefined} />
        </label>
        {#if errors.email}<p>{errors.email[0]}</p>{/if}
        <label>
          Message
          <textarea name="message" rows="5"></textarea>
        </label>
        <input type="hidden" name="_redirect" value={`${PUBLIC_SITE_URL}/contact/thanks`} />
        <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
        {#if status === "error" && !errors.email}<p role="alert">{message}</p>{/if}
        <button disabled={status === "sending"}>{status === "sending" ? "Sending" : "Send"}</button>
      </form>
    {/if}

    Tambahkan src/routes/contact/thanks/+page.svelte sebagai tujuan redirect.

Jika Anda memakai CSP SvelteKit

Jika kit.csp dikonfigurasi, izinkan Ikiform untuk kiriman fetch maupun kiriman formulir biasa. Jika tidak, browser akan memblokir salah satunya.

svelte.config.js
const config = {
  kit: {
    csp: {
      directives: {
        "connect-src": ["self", "https://ikiform.com"],
        "form-action": ["self", "https://ikiform.com"],
      },
    },
  },
};

export default config;

Domain yang diizinkan

Cantumkan domain produksi plus host pratinjau Anda.

Tempat formulir berjalanTambahkan ke Domain yang diizinkan
vite devlocalhost. Ini cocok dengan http://localhost:5173: Ikiform hanya membandingkan nama host, tidak pernah port.
Domain Andaexample.com, yang juga mencakup www.example.com
Vercelyour-project.vercel.app. URL pratinjau seperti your-project-git-branch-team.vercel.app tidak cocok dengannya; tambahkan host pratinjau persisnya selama Anda menguji.
Cloudflare Pagesyour-project.pages.dev. URL pratinjau seperti abc123.your-project.pages.dev adalah subdomainnya, jadi sudah cocok.
Netlifyyour-site.netlify.app. Deploy preview (deploy-preview-12--your-site.netlify.app) dan branch deploy (branch--your-site.netlify.app) bukan subdomainnya, jadi tambahkan host pratinjau persisnya selama Anda menguji.
  • Jangan pernah menambahkan vercel.app, pages.dev, atau netlify.app saja. Setiap situs di host itu akan cocok, termasuk milik orang lain.

Daftar periksa pengujian

  1. Jalankan dev server dengan localhost di domain yang diizinkan, lalu kirim. Pesan terima kasih seharusnya menggantikan formulir.
  2. Jalankan vite build dan pastikan output-nya berisi contact.html yang sudah memuat formulir.
  3. Matikan JavaScript, muat ulang, lalu kirim. Di domain https: Anda, Anda seharusnya mendarat di /contact/thanks.
  4. Kirim dari deploy pratinjau dan pastikan tidak ditandai spam.

Pemecahan masalah

Yang Anda lihatAlasanSolusi
Build gagal dengan pesan bahwa PUBLIC_IKIFORM_FORM_ID tidak diekspor oleh $env/static/publicVariabelnya tidak diatur di tempat build berjalanTambahkan ke .env secara lokal dan ke pengaturan build host Anda.
Tidak terjadi apa-apa saat dikirim, dan console menampilkan error CORS tentang header x-sveltekit-actionuse:enhance di formulir yang mengirim ke luar aplikasi AndaHapus dan pertahankan handler onsubmit.
Browser menolak mengirim formulir karena form-action atau connect-srckit.csp tidak mencantumkan IkiformTambahkan https://ikiform.com ke kedua direktif.
Tanpa JavaScript, Anda mendarat di halaman terima kasih IkiformPUBLIC_SITE_URL memakai http:, atau domainnya tidak ada di domain yang diizinkanGunakan alamat https: Anda dan tambahkan domainnya.
Kiriman masuk ke filter spam dengan origin_mismatchHalaman yang mengirim tidak ada di domain yang diizinkan formulirTambahkan host dari tabel di atas. Jika Reject dipilih, kiriman yang sama mendapat 403 origin_not_allowed.