Jika kamu pernah membuat form kontak dan melihat seluruh halaman reload setelah user mengklik "Submit," kamu pasti tahu betapa mengganggunya pengalaman tersebut. Menggunakan teknik submit form HTML dengan fetch javascript, kamu bisa mengirim data form ke backend endpoint di background, menjaga user tetap di halaman yang sama, dan menampilkan pesan sukses atau error yang bersih tanpa refresh halaman penuh. Tutorial ini akan memandu kamu melalui setiap langkah, dari menulis HTML dasar hingga mengarahkan panggilan fetch() ke endpoint Sendform agar submission kamu langsung masuk ke inbox atau workflow yang terhubung.
Poin Penting:
- Fetch API memungkinkan kamu submit data form tanpa reload halaman, memberikan pengalaman yang lebih smooth untuk user.
- Menangkap event
submitdan memanggilpreventDefault()adalah fondasi dari pola submit form ajax. - Sendform menyediakan URL endpoint siap pakai, jadi kamu butuh nol kode backend untuk menerima dan menyimpan submission.
- Penanganan response yang tepat (menampilkan feedback sukses atau error) sama pentingnya dengan mengirim data dengan benar.
Daftar Isi
Mengapa Menggunakan fetch() Daripada Submit Form Default
Perilaku default browser untuk submit form melakukan satu hal: serialize field form, kirim request POST (atau GET) ke URL action, lalu load response apa pun yang dikembalikan server. Artinya user melihat flash putih, kehilangan posisi scroll mereka, dan menunggu halaman baru untuk dimuat. Pada koneksi lambat, ini terasa rusak.
Fetch API menyelesaikan ini dengan membuat HTTP request secara programmatic, sepenuhnya dalam JavaScript, tanpa navigasi. Ini memungkinkan pola submit form tanpa reload halaman yang membuat user tetap engaged dan memberi kamu kontrol penuh atas setiap aspek user experience, termasuk loading state, feedback validasi inline, dan banner sukses yang animatif.
Alasan praktis tambahan untuk memilih fetch():
- Kamu bisa attach custom header (misalnya, token CSRF atau authorization key) yang tidak bisa dikirim plain HTML form.
- Kamu bisa serialize data sebagai JSON,
FormData, atau string URL-encoded tergantung apa yang diharapkan endpoint. - Error handling eksplisit. Kamu yang menentukan apa arti "failure" dan bagaimana mengkomunikasikannya.
- Bekerja di situs statis apa pun, termasuk yang dihosting di GitHub Pages, Netlify, atau CDN, karena logiknya sepenuhnya ada di browser.
Catatan: Jika kamu bekerja dengan website builder seperti Webflow, WordPress, atau Hugo, pendekatan fetch() yang sama berlaku. Lihat panduan kami tentang cara mengintegrasikan Sendform dengan website builder kamu untuk tips spesifik platform.
Setup HTML Form Dasar
Sebelum menulis satu baris JavaScript pun, kamu butuh HTML form yang terstruktur dengan baik. Detail kuncinya adalah kamu tidak butuh atribut action yang menunjuk ke mana pun, karena JavaScript akan menangani submission. Namun, kamu memang ingin atribut name yang bermakna di setiap input - ini menjadi key field dalam payload yang dikirim.
<form id="contact-form" novalidate>
<div>
<label for="name">Nama Kamu</label>
<input type="text" id="name" name="name" required placeholder="Jane Smith">
</div>
<div>
<label for="email">Alamat Email</label>
<input type="email" id="email" name="email" required placeholder="[email protected]">
</div>
<div>
<label for="message">Pesan</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit">Kirim Pesan</button>
<!-- Area feedback -->
<div id="form-feedback" aria-live="polite"></div>
</form>Beberapa hal yang perlu diperhatikan dalam markup ini:
novalidatepada element form menonaktifkan bubble validasi browser native, memberi kamu kontrol penuh atas error messaging dalam JavaScript.- Div
id="form-feedback"denganaria-live="polite"adalah tempat pesan sukses dan error akan muncul. Atribut ARIA memastikan screen reader mengumumkan feedback secara otomatis. - Setiap input memiliki
id(untuk asosiasi label) danname(untuk payload form).
Menangkap Event Submit
Langkah pertama dalam submit form javascript adalah mencegat perilaku default browser. Kamu melakukan ini dengan mendengarkan event submit pada element form dan langsung memanggil event.preventDefault().
const form = document.getElementById('contact-form');
form.addEventListener('submit', async function (event) {
event.preventDefault(); // Stop navigasi halaman default
// Validasi client-side dasar
const name = form.elements['name'].value.trim();
const email = form.elements['email'].value.trim();
const message = form.elements['message'].value.trim();
if (!name || !email || !message) {
showFeedback('Mohon isi semua field.', 'error');
return;
}
// Lanjut kirim data (bagian selanjutnya)
await submitForm({ name, email, message });
});Dengan memisahkan logika validasi dari network call, kamu membuat kode tetap readable dan mudah diperluas. Keyword async pada event handler memungkinkan kamu menggunakan await di dalamnya, yang membuat panggilan Fetch API data form terlihat synchronous dan menghindari promise chain yang nested dalam.
Mengarahkan fetch() ke Endpoint Sendform
Di sinilah pekerjaan sesungguhnya terjadi. Daripada membangun server sendiri untuk menerima, menyimpan, dan meneruskan submission form, kamu bisa menggunakan Sendform sebagai backend kamu. Setelah membuat form di dashboard Sendform, kamu mendapat URL endpoint unik. URL itu saja yang kamu butuhkan.
Fungsi submission di bawah menggunakan FormData API untuk membangun payload, yang diterima Sendform secara native:
async function submitForm(data) {
// Ganti URL ini dengan endpoint Sendform kamu yang sebenarnya
const SENDFORM_ENDPOINT = 'https://sendform.net/id/YOUR_FORM_ID';
const formData = new FormData();
formData.append('name', data.name);
formData.append('email', data.email);
formData.append('message', data.message);
try {
const response = await fetch(SENDFORM_ENDPOINT, {
method: 'POST',
body: formData,
});
if (response.ok) {
showFeedback('Terima kasih! Pesan kamu telah terkirim.', 'success');
form.reset();
} else {
const errorData = await response.json().catch(() => ({}));
const errorMsg = errorData.message || 'Ada yang salah. Silakan coba lagi.';
showFeedback(errorMsg, 'error');
}
} catch (networkError) {
showFeedback('Error jaringan. Periksa koneksi kamu dan coba lagi.', 'error');
}
}Keputusan kunci yang dibuat dalam kode ini:
- Tidak ada header
Content-Typeyang diset manual. Ketika kamu pass objekFormDatasebagai body, browser otomatis set boundarymultipart/form-datayang benar. - Pengecekan
response.okmencakup semua status code HTTP 2xx, bukan hanya 200. Ini lebih robust daripada membandingkanresponse.status === 200. try/catchluar menangkap failure level network (error DNS, state offline) yang tidak akan pernah dilihatresponse.ok.
Menangani Response - Pesan Sukses dan Error
Mengirim data hanya setengah pekerjaan. User butuh feedback yang immediate dan jelas. Fungsi helper showFeedback() yang direferensikan di atas menulis pesan ke dalam div feedback yang kamu tambahkan ke HTML:
function showFeedback(message, type) {
const feedbackEl = document.getElementById('form-feedback');
feedbackEl.textContent = message;
feedbackEl.className = type === 'success' ? 'feedback-success' : 'feedback-error';
}Ini sengaja minimal. Dalam project nyata kamu mungkin mengganti textContent dengan komponen animasi atau library toast notification, tapi polanya tetap sama: update DOM berdasarkan hasil panggilan fetch().
Untuk skenario yang lebih advanced, seperti redirect ke halaman thank-you custom atau memicu otomasi downstream setelah submission, cek artikel kami tentang cara mengotomatisasi workflow form dengan webhook, Zapier, dan API.
Best Practices dan Tips
Membuat kode bekerja adalah satu hal. Mengirimkannya dengan cara yang tahan dalam production adalah hal lain. Berikut tips terpenting yang perlu diingat:
- Disable tombol submit selama request. Set
button.disabled = truesebelum memanggilfetch()dan enable kembali dalam blokfinally. Ini mencegah submission duplikat jika user mengklik beberapa kali. - Tampilkan loading state. Ubah teks tombol menjadi "Mengirim..." atau tambahkan spinner class saat request sedang berjalan. User yang tidak melihat feedback sering mengira tidak terjadi apa-apa dan mengklik lagi.
- Validasi di server side juga. Validasi client-side untuk user experience. Sendform dan layanan backend apa pun harus memperlakukan semua data masuk sebagai tidak terpercaya.
- Gunakan HTTPS di mana-mana. Mengirim data form melalui HTTP plain mengekspos input user dalam transit. Endpoint Sendform adalah HTTPS secara default, tapi pastikan halaman kamu sendiri juga disajikan melalui HTTPS.
- Tambahkan proteksi spam. Field honeypot atau integrasi CAPTCHA mengurangi submission sampah secara signifikan. Untuk pandangan mendalam tentang topik ini, lihat panduan kami tentang best practices proteksi spam untuk form.
- Test path error dengan sengaja. Sementara ubah URL endpoint ke sesuatu yang invalid dan konfirmasi pesan error kamu muncul. Kebanyakan developer hanya test happy path.
- Jaga URL endpoint keluar dari version control. Jika project kamu open source, simpan endpoint Sendform dalam environment variable atau config file yang terdaftar di
.gitignore.
User situs statis: Jika project kamu adalah situs Hugo, Eleventy, atau HTML plain tanpa server, pendekatan fetch() yang dijelaskan di sini adalah metode yang direkomendasikan. Baca lebih lanjut dalam panduan kami tentang penanganan form serverless untuk situs statis.
Kesimpulan
Mengganti submission form default dengan panggilan fetch() adalah salah satu peningkatan berdampak tertinggi yang bisa kamu lakukan pada form kontak atau lead-capture apa pun. Hasilnya adalah pengalaman yang lebih cepat dan profesional yang membuat user tetap di halaman kamu dan memberi kamu kontrol penuh atas feedback messaging. Pasangkan dengan endpoint Sendform dan kamu menghilangkan kebutuhan akan kode server-side sepenuhnya. Form kamu live, submission kamu sampai ke inbox kamu, dan user kamu tidak pernah melihat reload halaman yang mengganggu. Buat endpoint Sendform gratis kamu hari ini dan dapatkan submission pertama kamu dalam hitungan menit.
Pertanyaan yang Sering Diajukan
Ya. Karena fetch() berjalan sepenuhnya di browser, ia bekerja di situs HTML statis, project JAMstack, dan platform apa pun yang menyajikan HTML. Kamu tidak butuh server sendiri. Satu-satunya persyaratan adalah endpoint (seperti URL Sendform) yang bisa menerima request POST.
fetch() adalah pengganti modern untuk XMLHttpRequest. Ia menggunakan Promise, mendukung async/await, dan memiliki API yang lebih bersih. Untuk project baru, fetch() selalu diutamakan. Keduanya mencapai hasil submit form ajax yang sama, tapi fetch() membutuhkan kode boilerplate yang jauh lebih sedikit.
Tidak. Ketika kamu pass objek FormData sebagai body, browser otomatis set Content-Type ke multipart/form-data dan menyertakan string boundary yang benar. Mengaturnya manual justru akan merusak request dengan menghilangkan nilai boundary tersebut.
Daftar di Sendform, buat form baru di dashboard, dan copy URL endpoint yang dihasilkan. Paste URL tersebut sebagai target dalam panggilan fetch() kamu. Submission akan diteruskan ke alamat email yang dikonfigurasi segera.
Network failure menyebabkan Promise fetch() reject, yang ditangkap oleh blok try/catch luar dalam contoh kode. User melihat pesan "Error jaringan" yang kamu definisikan. Submission tidak antri otomatis; user harus coba lagi setelah konektivitas pulih.