D
P
0
← Semua artikel Read in English

JavaScript, DOM & Animasi Browser

Klik Tanggal Malah Mengirim Seluruh Form? `<button>` Tanpa `type` di Dalam `<form>` Defaultnya Submit

· · 4 menit baca
Klik Tanggal Malah Mengirim Seluruh Form? `<button>` Tanpa `type` di Dalam `<form>` Defaultnya Submit

Kalender ketersediaan di form tambah properti tidak tampil sebagai kalender. Yang muncul cuma satu baris teks nyambung, SuMoTuWeThFrSa123..., deretan nama hari dan angka tanggal yang menempel tanpa jarak. Itu kerusakan pertama, dan dia hidup di lapisan CSS.

Kerusakan keduanya sama sekali tidak berhubungan dengan itu dan baru ditutup di rilis sesudahnya. Di form yang sama, mengklik sel tanggal tidak men-toggle tanggal itu, dan mengklik panah nav bulan tidak mengganti bulan. Dua-duanya mengirim seluruh form.

Dua kalender, satu yang punya CSS

Produk ini punya dua kalender. Satu di tab dashboard, satu lagi di form tambah properti. Keduanya kelihatan seperti komponen kembar, tapi prefiks class-nya berbeda. Yang di dashboard memakai .avail-calendar__* dan punya CSS lengkap. Yang di form memakai .cal__*, dan class dengan prefiks itu tidak pernah punya CSS sama sekali.

Hasilnya persis seperti yang terlihat di layar. Elemen-elemennya semua hadir di DOM, tapi tanpa grid dan tanpa ukuran, mereka jatuh jadi aliran teks biasa. Nama hari menempel ke nama hari berikutnya, angka tanggal menempel ke angka berikutnya. Kalendernya tidak rusak, dia cuma tidak pernah dikasih bentuk. Kondisi itu bertahan sejak rilis yang jauh lebih awal, lama sebelum rilis yang akhirnya menambahkan type="button".

Perbaikannya menambahkan satu blok CSS .cal__* yang meniru kalender dashboard: grid tujuh kolom, tombol hari, dan state untuk tanggal yang diblokir maupun yang sudah lewat. Kira-kira begini kerangkanya.

.cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}
 
.cal__day {
  /* tombol hari */
}
 
.cal__day--blocked,
.cal__day--past {
  /* tanggal yang diblokir dan tanggal yang sudah lewat */
}

Di perbaikan yang sama, nama hari dan nama bulan yang sebelumnya di-hardcode dalam bahasa Inggris diganti supaya dibaca dari objek i18n aplikasi, lewat appData.i18n.months dan appData.i18n.weekdaysShort. Setelah itu kalendernya mengikuti bahasa situs, bukan bahasa yang kebetulan tertulis di kode.

Setiap klik mengirim form

Kerusakan kedua ada di markup tombolnya. Sel hari dan panah nav bulan itu elemen <button>, dan tidak satu pun membawa atribut type.

<form action="/submit-listing" method="post">
  <button data-calendar-day="2026-05-17">17</button>
</form>

Di dalam <form>, <button> tanpa type defaultnya type="submit". Bukan netral, bukan button, tapi submit. Jadi tombol yang niatnya cuma memblokir satu tanggal sebenarnya adalah tombol kirim, dan browser memperlakukannya persis seperti itu. Begitu juga panah ganti bulan, yang bahkan tidak menyentuh data apa pun.

Tidak ada yang salah secara sintaks di sini. <button> tanpa type adalah HTML yang valid, jadi tidak ada validator yang mengeluh. Yang menggigit cuma nilai defaultnya, dan gejalanya bukan pesan error melainkan form yang terkirim di waktu yang aneh.

Perbaikannya satu atribut

Perbaikannya menambahkan type="button" ke tombol hari kalender dan tombol nav bulan. Catatan untuk kasus ini menyimpan satu potong markupnya berikut komentar penjelas.

<!-- button in a form with no type defaults to submit -->
<button type="button" data-calendar-day="2026-05-17">17</button>

Perbaikannya berhenti di situ. Tidak ada logika baru, tidak ada handler yang diubah, cuma satu atribut yang mengembalikan tombol jadi tombol biasa.

Yang berubah setelah itu

Setelah atribut itu masuk, klik hari men-toggle status blocked dan selnya berubah merah, statusnya tersimpan lewat endpoint availability/toggle yang menjawab 200, dan tidak ada form yang terkirim. Nav bulannya juga berfungsi seperti seharusnya.

Verifikasinya dilakukan langsung di produksi memakai tiga peran akun yang berbeda: pemilik, tamu, dan admin.

Bentuk yang berulang di projek ini

Yang membuat saya berhenti sebentar bukan bug-nya sendiri, tapi berapa kali bentuk yang mirip muncul di projek yang sama.

Komponen unggah foto pernah rilis tanpa CSS sama sekali. Dropzone-nya jadi tidak kelihatan bisa diklik dan thumbnail-nya dirender seukuran aslinya, dan itu bagian besar dari keluhan bahwa fiturnya "gabisa" dipakai.

Kartu checkbox amenities juga begitu, tidak punya CSS sama sekali. Keluhannya terdengar seperti masalah logika, seolah multi-select-nya tidak jalan. Padahal multi-select-nya sudah jalan dari awal karena memang checkbox. Celah sebenarnya cuma kartu yang tidak pernah digayakan.

Ada juga kebalikannya, dan yang ini lebih sunyi. Gejalanya masuk lewat laporan klien, akar masalahnya yang saya kejar sendiri. Di halaman detail properti, di bawah 1024px widget booking-nya display:none dan seharusnya digantikan bar booking yang sticky. CSS untuk bar itu ada. Markup-nya tidak pernah ada di template. Jadi di mobile dan tablet tidak ada tombol Reserve sama sekali, dan pengunjung tidak bisa memesan dari sana.

Satu peringatan supaya tidak semua laporan langsung dituduh CSS yang hilang. Klien pernah melaporkan unggah foto "gabisa klik" setelah unggah ulang, dan itu ternyata cache peramban, bukan kesalahan kode. Buktinya sederhana: di jendela Incognito fiturnya jalan.

Yang saya bawa pulang