Event Delegation - JavaScript
Published: 2024-03-17 04:13:56

Event delegation dalam JavaScript adalah suatu teknik untuk menangani event bubbling lebih efisien ? Apa itu event bubbling ? Sebelum kesana kita perlu paham dulu mengenai event capturing, bubbling dan propagation. Bubbling dan capturing adalah 2 fase dari propagation. Sederhananya bubbling adalah DOM traversal dari target ke root, sedangkan capturing adalah kebalikannya yaitu DOM traversal dari root ke target. Target adalah elemen yang dikenakan event (children), root adalah induk (parent) dari elemen yang dikenakan event. Misal kita punya kode html seperti ini :

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="styles.css" />
    <title>Event Delegation</title>
  </head>
  <body>
    <header>
      <ul>
        <li><a class="btn btnScroll1" href="#section-1">Section 1</a></li>
        <li><a class="btn btnScroll2" href="#section-2">Section 2</a></li>
        <li><a class="btn btnScroll3" href="#section-3">Section 3</a></li>
      </ul>
    </header>
    <section class="section" id="section-1">
      <p>This is section 1</p>
    </section>
    <section class="section" id="section-2">
      <p>This is section 2</p>
    </section>
    <section class="section" id="section-3">
      <p>This is section 3</p>
    </section>
    <script src="eventDel.js"></script>
  </body>
</html>

```
Jika kita mengaplikasikan click event misalnya kepada salah satu elemen button, maka gambarannya sebagai berikut :

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pti8gabik9ebrznhmdah.png)

Capturing sangat jarang digunakan sehingga kita akan fokus pada bubbling. Berikut kode JavaScript-nya :

```javascript
'use strict';

const header = document.querySelector('header');
const button1 = document.querySelector('.btnScroll1');

function printHead() {
  console.log('header');
}
function printBtn() {
  console.log('button1');
}

button1.addEventListener('click', printBtn);
header.addEventListener('click', printHead);

```
Apabila kita klik tombol Section 1 maka hasil di console sebagai berikut :

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/323lv3uozny0sj7t9h6v.png)

Terlihat bahwa sebenarnya eksekusi event handler 'click' tidak hanya pada target saja (button1), tapi juga pada parent element (header) sehingga muncul keduanya di console. Bagaimana caranya supaya event handler hanya mengeksekusi target saja ? Kita gunakan `event.stopPropagation()` untuk mencegah event bubbling ke parent element sebagai berikut :

```javascript
function printBtn(event) {
  event.stopPropagation();
  console.log('button1');
}
```

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqb5d1sstngrvngk5qpc.png)

Terlihat bahwa console hanya menampilkan `button1` dan tidak `header`. `addEventListener` sebenarnya memiliki 1 parameter terakhir selain event dan function yaitu bolean (tru/false). Parameter ini secara default bernilai false sehingga tidak perlu ditulis, jika diisi true maka akan mengaktifkan capturing phase dan menonaktifkan bubbling phase. Contohnya sebagai berikut :

```javascript
function printHead() {
  console.log('header');
}
function printBtn() {
  console.log('button1');
}
button1.addEventListener('click', printBtn);
header.addEventListener('click', printHead, true);
```

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zaesbcr99erkdvhm7yip.png)

Terlihat bahwa `header` akan muncul pertama kali sebelum `button1` di console, ini dikarenakan capturing phase dieksekusi pada `header` kemudian turun ke `button1` (target).

Oke sekarang kita masuk ke event delegation, apa itu event delegation ? Jadi semisal kita punya banyak sekali tombol navigasi dalam suatu `div`, bagaimana kita mengakses dan mengeksekusi tombol-tombol tersebut ?

1. Memakai perintah `querySelectarAll()` dan `forEach` seperti yang pernah kita lakukan pada contoh [smooth scrolling](https://dev.to/boibolang/smooth-scrolling-aj1). Cara ini efektif jika elemennya tidak banyak tapi akan sangat mempengaruhi performa jika elemennya terlalu banyak.
2. Memakai event delegation, dengan cara menyeleksi parent element (root) dan memastikan elemen (tombol) yang dieksekusi serta meng-assign (delegate) perintah kepada masing-masing tombol.

```javascript
// Event delegation
// Menambahkan event listener ke parent element
document.querySelector('header').addEventListener('click', function (e) {
  e.preventDefault();

  // Memastikan elemen yang dieksekusi dan meng-assign perintah
  if (e.target.classList.contains('btn')) {
    const id = e.target.getAttribute('href');
    document.querySelector(id).scrollIntoView({
      behaviour: 'smooth',
    });
  }
});
```
Hasilnya sama dengan smooth scrolling seperti sebelumnya, namun kali ini dengan event delegation.

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csb0f9j8v3jwc7u734fw.gif)