ID formulir

JavaScript biasa

Tingkatkan formulir HTML secara progresif dengan fetch: error field inline, pesan status, dan tanpa reload halaman.

Halaman ini tidak butuh build step maupun paket. Formulir berfungsi sebagai kiriman HTML biasa saat JavaScript mati; saat JavaScript aktif, skrip mengirim dengan fetch dan menampilkan hasilnya inline.

contact.html
<form id="contact" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post" novalidate>
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required aria-describedby="email-error" />
  <p id="email-error" data-error-for="email"></p>
  <label for="message">Message</label>
  <textarea id="message" name="message"></textarea>
  <p id="message-error" data-error-for="message"></p>
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
  <p role="status" data-status></p>
</form>

<script type="module">
  const form = document.querySelector("#contact");
  const button = form.querySelector("button");
  const status = form.querySelector("[data-status]");

  function showErrors(fields = {}) {
    for (const slot of form.querySelectorAll("[data-error-for]")) {
      const messages = fields[slot.dataset.errorFor];
      slot.textContent = messages ? messages[0] : "";
      form.elements[slot.dataset.errorFor]?.setAttribute("aria-invalid", messages ? "true" : "false");
    }
  }

  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    button.disabled = true;
    status.textContent = "Sending";
    try {
      const response = await fetch(form.action, {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(form),
      });
      const result = await response.json();
      showErrors(result.ok ? {} : result.error.fields);
      status.textContent = result.ok ? "Thanks, we got it." : result.error.message;
      if (result.ok) form.reset();
    } catch {
      status.textContent = "Couldn't reach the server. Check your connection and try again.";
    } finally {
      button.disabled = false;
    }
  });
</script>
  • Accept: application/json membuat Ikiform menjawab dengan JSON, bukan redirect.
  • result.error.fields diberi key berdasarkan ID field; skrip menulis pesan pertama di bawah setiap field.
  • fetch hanya me-reject saat jaringan gagal. Error HTTP tetap resolve, dengan envelope error di body.
  • Respons 429 membawa Retry-After, yang bisa dibaca kode browser karena Ikiform mengeksposnya lewat CORS.

Dengan pemeriksaan manusia Ikiform

Halaman pemeriksaan perantara hanya muncul untuk navigasi browser biasa. Kiriman fetch ke formulir dengan pemeriksaan Ikiform akan mendapat 403 challenge_required. Gunakan challenge dari SDK lewat bundler Anda, atau biarkan formulir mengirim tanpa JavaScript.