Skip to main content
Submit your form without reloading the page using JavaScript’s Fetch API. This lets you show inline success or error messages, keep users on the same page, and build a smoother form experience.
<div class="flex min-h-screen w-full items-center justify-center bg-neutral-100 p-4 text-neutral-900">
  <div class="w-full max-w-lg space-y-6 rounded-2xl border border-neutral-200 bg-white p-4 py-10 sm:p-10">
    <div class="space-y-1 text-center">
      <h2 class="text-3xl font-semibold">Contact Us</h2>
      <p class="text-neutral-600">
        Fill up the form below to send us a message.
      </p>
    </div>

    <form
      action="https://pipedform.com/f/{form_id}"
      method="POST"
      class="space-y-4 text-sm"
      id="contact-form"
    >
      <div class="flex flex-col gap-1">
        <label for="name" class="font-medium">Name</label>
        <input
          name="name"
          id="name"
          required
          placeholder="John Doe"
          class="h-9.5 rounded-lg border border-neutral-300 px-3 transition-all outline-none focus:border-neutral-400"
        />
      </div>
      <div class="flex flex-col gap-1">
        <label for="email" class="font-medium">Email</label>
        <input
          name="email"
          type="email"
          id="email"
          required
          placeholder="johndoe@example.com"
          class="h-9.5 rounded-lg border border-neutral-300 px-3 transition-all outline-none focus:border-neutral-400"
        />
      </div>
      <div class="flex flex-col gap-1">
        <label for="message" class="font-medium">Message</label>
        <textarea
          name="message"
          id="message"
          required
          placeholder="Enter your message..."
          class="rounded-lg border border-neutral-300 px-3 py-2 transition-all outline-none focus:border-neutral-400"
        ></textarea>
      </div>
      <p class="contact-form__result text-neutral-600 data-[status=error]:text-red-600 data-[status=success]:text-green-600"></p>
      <button
        type="submit"
        class="h-10 cursor-pointer rounded-lg bg-neutral-900 px-8 font-medium text-white transition-all hover:bg-neutral-800"
      >
        Send
      </button>
    </form>
  </div>
</div>
const form = document.getElementById('contact-form');
const result = document.querySelector('.contact-form__result');

let timeout;
form.addEventListener('submit', async (e) => {
  e.preventDefault();
  clearTimeout(timeout);

  const formEl = e.currentTarget;
  const data = JSON.stringify(Object.fromEntries(new FormData(formEl)));
  const destinationUrl = formEl.action;

  result.innerHTML = 'Submitting...';

  const res = await fetch(destinationUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: data,
  });
  const json = await res.json();

  result.innerHTML = json.message;

  if (!res.ok) {
    result.dataset.status = 'error';
  } else {
    result.dataset.status = 'success';
    form.reset();
  }

  timeout = setTimeout(() => {
    result.dataset.status = '';
    result.innerHTML = '';
  }, 5000);
});