Belajar Javascript DOM

Trik Menambahkan Event Menggunakan Delegation

Materi ini memiliki 1 buah lampiran. Namun Anda tidak dapat mengakses lampiran karena belum terdaftar di kursus ini. Klik disini untuk mendaftar.

Kita melanjutkan video ini dari materi sebelumnya. Saya sudah menambahkan fitur baru, dimana kita bisa membuat card atau kartu baru. Kita tinggal mengetikkan nama, misalkan “Baru”, dan menekan tombol “add”. Browser membuatkan kartu baru yang tampilannya sama persis dengan kedua kartu yang sudah ada. Namun perhatikan kalau saya menekan tombol X pada kartu lama, maka kartunya akan menghilang. Sedangkan kalau saya menekan tombol X pada kartu baru, maka tidak terjadi apa-apa.

Mengapa hal ini bisa terjadi? Kalau kita lihat lagi ke kode Javascript-nya, hal ini terjadi karena kita menjalankan addEventListener pada saat halaman baru ditampilkan. Pada saat itu hanya ada 2 kartu bawaan dari HTML. Jadi pada saat kita menambahkan kartu baru, maka tombol pada kartu tersebut belum memiliki event listener.

Solusi gampang dari masalah ini adalah, kita panggil addEventListener pada saat membuat kartu baru. Sebagai contoh, pada function addNewCard, disini ada bagian kode yang membuat tombolnya. Kita bisa tambahkan kode:

btn.addEventListener("click", onButtonCloseClick);

Kalau kita refresh browser dan kita coba lagi membuat kartu baru. Maka kartu baru yang sekarang sudah bisa dihilangkan melalui tombol tutup. Namun kalau kita lihat kembali ke kode Javascript. Kita memiliki 2 kode addEventListener untuk tombol tutup. Yang pertama adalah yang dijalankan untuk kartu yang sudah ada dari halaman HTML-nya. Sedangkan yang kedua adalah untuk kartu baru ditambahkan.

Ada trik lain yang bisa kita gunakan agar kita hanya perlu menambahkan Event Listener 1 kali saja. Trik ini bernama Event Delegation. Nah, bagi teman-teman yang ingin tau bagaimana caranya, tontonlah video ini sampai selesai. Akan kita bahas tuntas.

Sebelum kita melanjutkan ke Event Delegation, teman-teman mesti tau terlebih dahulu konsep yang namanya Event Bubbling. Untuk itu, mesti kita coba langsung di kode kita ya. Kita modifikasi sedikit. Pada function onButtonCloseClick, kita komentari baris untuk menghilangkan kartunya. Kita ganti menjadi alert(“onButtonClick”). Jadi kita hanya perlu tau bahwa tombol tutup ini diklik.

Kita coba di browser ya. Sekarang apabila tombol tutup diklik, sudah tidak menghilangkan kartu, melainkan hanya memberitahu kita bahwa terjadi onButtonClick.

Kita lihat kembali kode HTML. Perhatikan bahwa tombol tutup ini, berada di dalam div dengan kelas “card”. Artinya div “card” ini adalah orang tua dari tombol. Dan div “card” memiliki 2 buah anak, yaitu teks dari kartu, dan tombol tutup.

Kita pindah ke Javascript, kita tambahkan event onClick pada div “card”. Kita loop dahulu for(el of document.getElementsByClassName(“card”). Lalu kita tambahkan event baru “click” dengan function baru yang menampilkan pesan “onCardClick”.

for(el of document.getElementsByClassName("card"))
{
  el.addEventListener("click", evt => alert("onCardClick"));
}

Kita simpan dan jalankan di browser. Kita coba klik tombol tutup. Pertama kita mendapatkan pesan onButtonClick. Kemudian kita mendapatkan pesan lagi onCardClick. Sedangkan kalau kita hanya mengklik di bagian teks-nya, maka kita hanya mendapatkan satu pesan onCardClick.

Kita lihat lagi ke html ya. Perhatikan bahwa div “card”, berada di dalam div dengan id dan class yang sama yaitu card-container. Sekarang kita tambahkan lagi onClick pada card-container. Disini kita bisa gunakan method getElementById agar kodenya menjadi lebih sederhana.

document.getElementById("card-container").addEventListener(
  "click", evt => alert("onCardContainerClick")
);

Kita coba di browser. Sekarang kalau kita mengklik tombol tutup, maka kita mendapatkan pesan “onButtonClick”, “onCardClick”, dan “onCardContainerClick”. Nah, dari sini teman-teman bisa melihat ya konsep dari Event Bubbling. Kita lihat lagi kode HTML-nya.

Jadi pada saat terjadi klik pada tombol close, maka browser akan memanggil event click pada tombol. Kemudian terjadi bubbling. Browser juga memanggil event click pada element yang berada di atas tombol, atau parent-nya, yaitu div “card”. Maka kita menerima pesan lagi yaitu “onCardClick”. Kemudian event click-nya naik lagi ke atas, ke div “card-container” dan kita menerima pesan “onCardContainerClick”. Dan event click ini akan naik terus ke atas, yaitu ke tag body, tag html, hingga ke bagian paling atas yaitu document.

Nah, apabila teman-teman tidak ingin terjadi bubbling, maka kita bisa memanggil method yang namanya stopPropagation(). Sebagai contoh, kita taruh pada function onButtonCloseClick. Namun sebelumnya kita mesti tambahkan parameter dahulu yaitu evt. Barulah kita bisa memanggil methodnya evt.stopPropagation().

Kalau kita coba di browser, kita tekan tombol Tutup. Kali ini kita hanya menerima pesan onButtonClick. Tidak ada pesan lain. Karena method stopPropagation mencegah terjadinya bubbling. Browser sudah tidak memanggil event “click” pada parent-nya tombol.

Nah, dari konsep Event Bubbling ini, kemudian lahirlah teknik baru untuk menambahkan event. Daripada kita harus menambahkan event “click” di setiap tombol, kenapa kita tidak menuliskan satu event click saja di card-container? Mungkin teman-teman jadi bingung. Kenapa mesti di card-container? Apa keuntungannya? Sekarang perhatikan ya. Kalau saya menambahkan kartu baru. Perhatikan kalau saya klik ke tombol tutup yang baru. Tombol ini tidak memiliki event onButtonClick. Namun browser tetap menjalankan onCardContainerClick. Mengapa? Karena terjadi bubling. Kartu ini berada di dalam card-container.

Disinilah lahir teknik baru dengan nama Event Delegation. Jadi kita menuliskan event pada parent-nya. Kemudian di dalam event, kita periksa kembali event ini terjadi pada anak yang mana? Karena anak dari card-container ini kan bisa saja ada beberapa tipe, bisa card, bisa card-text dan bisa juga button. Apabila klik ini terjadi pada button, barulah kita melakukan penghapusan terhadap kartu yang bersangkutan.

Kita coba praktek ya. Jadi semua kode di bagian atas ini kita komentari saja. Kita hanya menggunakan kode pada card-container ini saja. Dan berhubung function-nya agak panjang, lebih baik jangan menggunakan arrow function ya. Kita ubah menjadi function expresion dengan parameter evt. Isinya kita console.log dahulu parameter evt.

Kita coba di browser ya. Kita klik ke tombol Tutup. Kita lihat di console ada PointerEvent yang merupakan isi dari parameter evt. Dari evt ini kita mesti mencari informasi mengenai element anak mana yang mendapatkan klik dari kita. Scroll ke bawah ya, sampai kita menemukan property target, isinya adalah tombol btn-close. Jadi property inilah yang menunjukkan element anak mana yang sedang mendapatkan klik.

Kita ubah lagi kode kita ya. Jangan tampilkan evt, melainkan property evt.target. Kita coba lagi. Kalau kita klik ke tombol, maka targetnya adalah button btn-close. Kalau kita klik ke teks pada kartu, maka targetnya menjadi card-text. Sedangkan kalau kita klik ke ruang kosong, maka targetnya adalah card-container. Jadi kita tinggal memeriksa, element apakah target tersebut.

Untuk melihat lebih detil, kita ganti lagi kodenya ya. Dari console.log menjadi console.dir.

Kita coba lagi klik tombol tutup. Sekarang kita bisa melihat tombolnya sebagai Javascript Object. Kita bisa browse untuk melihat property dan method-nya ya. Property yang menunjukkan bahwa object ini adalah sebuah button adalah “nodeName”. Perhatikan bahwa “BUTTON” menggunakan huruf besar semuanya.

Jadi isi pertama dari fungsi onClick kita adalah memeriksa apakah target ini sebuah tombol? Apabila benar, maka kita hilangkan kartunya. Kodenya menjadi:

    if(evt.target.nodeName == "BUTTON")
    {
      evt.target.parentElement.style.display = "none";
    }

Kita jalankan lagi di browser. Sekarang kalau kita mengklik ke bagian teks, maka tidak terjadi apa-apa. Kalau kita coba klik ke tombol, maka kartunya menjadi hilang. Kita coba buat kartu baru. Dan kita klik ke tombol tutup pada kartu baru, maka kartu barunya turut hilang. Jadi teknik Event Delegation ini sudah berhasil memecahkan masalah kita, dengan cara penulisan kode yang sebenarnya lebih sederhana ya. Hanya saja konsepnya sedikit lebih sulit daripada konsep Event Handler yang biasa.

Dan satu hal lagi, apabila ternyata teman-teman memiliki beberapa button di dalam card, maka kita tidak bisa menggunakan cara ini, karena tombol apa pun yang ditekan akan menghilangkan kartu tersebut. Jadi kita mesti memeriksa secara lebih spesifik apakah jenis tombol yang ditekan. Dalam hal ini, akan lebih cocok kalau kita memeriksa apakah element memiliki kelas btn-close. Jadi kode if bisa kita ubah menjadi

    if(evt.target.classList.contains("btn-close"))
    {
      evt.target.parentElement.style.display = "none";
    }

Kalau coba lagi di browser, maka hasilnya sama ya. Yang berbeda hanya cara memeriksa element anaknya saja.

1 Jam 2 Menit

Dengan menggunakan fasilitas tanya jawab, maka Anda bisa bertanya dan akan dijawab langsung oleh instruktur kursus.

Anda belum terdaftar pada kursus ini sehingga tidak bisa mengajukan pertanyaan.