Mengatasi jQuery dan Metode getElementById Gagal Menemukan Element dalam DOM

Selasa, 28 Jun 2022

Kita dapat memanipulasi Element HTML sesuai kebutuhan kita melalui DOM. Sayangnya karena suatu kesalahan, maka javascript bisa gagal mengenali atau menemukan elemen yang dimaksud. Oleh sebab itu maka skript yang sudah ditulis menjadi tidak dapat bekerja dengan baik.

Beberapa waktu yang lalu saya mendapat kunjungan teman lama yang sudah lama hilang komunikasi. Teman lama tersebut datang kerumah sambil meminta tolong untuk membenahi aplikasi kerjaannya yang tidak dapat berjalan dengan baik. 

Aplikasi tersebut terhubung dengan API suatu sistem yang mana sudah terkenal dinegeri ini. Usut punya usut dari pengujian yang saya lakukan, sebenarnya koneksi aplikasi dan API sudah benar. Request dapat terkirim dan data sudah diterima dengan baik, masalahnya cuma pada bagaimana data dalam API dapat ditampilkan dan digunakan untuk trigger lanjutan.

Kegagalan aplikasi tersebut sebenarnya bersumber dari kegagalan skript menemukan element dengan id yang dimaksud untuk menampilkan data dari API untuk menjadi opsi pilihan yang hendak digunakan kembali untuk proses selanjutnya. Pada kasus teman saya kebetulan penyebab kegagalan menemukan elemen adalah akibat adanya element dengan id yang sama digunakan lebih dari sekali. Atau dengan kata lain terdapat "id ganda" dalam sebuah dokumen HTML.

Pada kasus ini id dapat ditemukan dan bukan menghasilkan nilai null, tapi masalahnya nilai yang dimasukkan dalam elemen tidak dapat muncul. Sehingga perlu dilakukan pencarian id ganda yang baru akan ditemukan dengan cara searching masing-masing element menggunakan fitur teks kode editor. 

Masih berhubungan dengan kasus milik teman saya tersebut, sebenarnya masih banyak penyebab lain yang mengakibatkan javascript gagal menemukan suatu Element. Kita dapat mencari penyebabnya dengan melacak pesan kesalahan "eror" yang ditunjukkan pada jendela console.

Mengatasi jQuery dan Metode getElementById Gagal


Eror yang Muncul Akibat Skrip Gagal Menemukan Element

Apasaja informasi masalah yang mungkin muncul akibat document.getElementById, atau bila dengan jQuery ditulis $("#id") atau metode yang lain gagal menemukan element dalam DOM?

Metode DOM mengembalikan hasil null dalam salah satu bentuk berikut:

Uncaught TypeError: Cannot set property '...' of null

Uncaught TypeError: Cannot set properties of null (setting '...')

Uncaught TypeError: Cannot read property '...' of null

Uncaught TypeError: Cannot read properties of null (reading '...')


Contoh Muncul Pesan jQuery Gagal Menemukan Elemen:

jQuery silently failing to bind an event handler

jQuery "getter" methods (.val(), .html(), .text()) returning undefined


Pada formulir umumnya muncul pesan bermasalah seperti berikut:

Uncaught TypeError: Cannot set property 'onclick' of null

Uncaught TypeError: Cannot read property 'addEventListener' of null

Uncaught TypeError: Cannot read property 'style' of null


Elemen yang Anda Cari tidak ditemukan pada DOM saat skrip Anda Berjalan

Posisi atau letak skrip yang bekerja pada DOM dapat memiliki pengaruh pada perilakunya. Browser mengurai dokumen HTML dengan urutan dari atas ke bawah. Elemen ditambahkan ke DOM dan skrip (umumnya) dieksekusi saat ditemui. Ini berarti bahwa urutan peletakan itu penting. Biasanya, skrip tidak dapat menemukan elemen yang muncul kemudian di markup karena elemen tersebut belum ditambahkan ke DOM.

Perhatikan contoh markup berikut; skrip #1 gagal menemukan <div> sementara skrip #2 berhasil:

skrip #1

<script>

  console.log("script #1:", document.getElementById("test")); // nol

</script>


skrip #2

<div id="test">div uji</div>

<script>

  console.log("script #2:", document.getElementById("test")); // <div id="tes" ...

</script>


Cara Mengatasi Kegagalan Menemukan Element

Jadi, apa yang harus Anda lakukan? Anda sebenarnya memiliki beberapa opsi:


Opsi 1: Pindahkan skrip Anda

Mengingat apa yang telah kita lihat dalam contoh di atas, solusi sederhana salah satunya mungkin cukup dengan memindahkan skrip Anda ke bawah elemen html, browser membaca script setelah melewati elemen yang ingin Anda akses. Bahkan, untuk waktu yang lama, menempatkan skrip di bagian bawah halaman dianggap sebagai praktik terbaik karena berbagai alasan. Dengan menggunakan cara ini, dokumen akan diuraikan terlebih dulu sebelum menjalankan skrip Anda:

<body>

  <button id="test">klik saya</button>

  <script>

    document.getElementById("test").addEventListener("click", function() {

      console.log("diklik:", ini);

    });

  </script>

</body><!-- tag penutup tubuh -->

Meskipun cara ini masuk akal dan merupakan opsi yang terbaik untuk browser lawas, cara ini punya batas dan sebenarnya sudah ada pendekatan modern yang lebih fleksibel. Silahkan pertimbangkan opsi yang lain selanjutnya.


Opsi 2: Menggunakan Atribut Penangguhan

Meskipun kami sudah menuliskan bahwa skrip, "(umumnya) dieksekusi berurutan saat ditemukan," browser modern memungkinkan Anda untuk menggunakan perilaku yang berbeda. Jika Anda menautkan skrip eksternal, Anda dapat menggunakan atribut defer.

[defer, atribut Boolean,] diatur untuk menunjukkan kepada browser bahwa skrip dimaksudkan untuk dieksekusi setelah dokumen diuraikan, tetapi sebelum mengaktifkan DOMContentLoaded.

Ini berarti Anda dapat meletakkan skrip yang sudah ditandai dengan penangguhan di mana saja, bahkan <head>, dan skrip tersebut harus memiliki akses ke DOM yang direalisasikan sepenuhnya.


<script src="https://gh-canon.github.io/misc-demos/log-test-click.js" defer></script>

<button id="test">klik saya</button>


Catatan penting...!

penggunaan defer hanya dapat dilakukan untuk skrip eksternal, yaitu: skrip yang memiliki atribut src.

waspadai dukungan browser tertentu, misalnya yaitu: implementasi buggy di IE <10


Opsi 3: Modul

Seperti dalam beberapa framework, pada umumnya dapat menggunakan modul JavaScript. Di antara perbedaan penting lainnya dari skrip standar (dicatat di sini), modul ditangguhkan secara otomatis dan tidak terbatas pada sumber eksternal. Sehingga anda bebas menggunakannya tanpa perlu menambahkan atribut ataupun memperhatikan posisi meletakkannya.

Setel jenis skrip Anda ke modul, misalnya.:

<script type="modul">

  document.getElementById("test").addEventListener("click", function(e) {

    console.log("diklik: ", ini);

  });

</script>

<button id="test">klik saya</button>


Opsi 4: Tunda dengan penanganan event

Tambahkan listener ke event yang diaktifkan setelah dokumen Anda diurai.

"event DOMContentLoaded"

DOMContentLoaded diaktifkan setelah DOM selesai dibuat dari penguraian awal, tanpa menunggu hal-hal lain seperti css atau gambar dimuat.

<script>

  document.addEventListener("DOMContentLoaded", function(e){

    document.getElementById("test").addEventListener("click", function(e) {

      console.log("diklik:", ini);

    });

  });

</script>

<button id="test">klik saya</button>


Window:load event

Peristiwa pemuatan diaktifkan setelah DOMContentLoaded dan sumber daya tambahan seperti CSS dan gambar telah dimuat. Karena alasan itu, ia menyala lebih lambat dari yang diinginkan untuk tujuan kita. Namun, jika Anda mempertimbangkan browser lama seperti IE8, dukungannya hampir universal. Memang, Anda mungkin menginginkan polyfill untuk addEventListener().

<script>

  window.addEventListener("load", function(e){

    document.getElementById("test").addEventListener("click", function(e) {

      console.log("diklik:", ini);

    });

  });

</script>

<button id="test">klik saya</button>


jQuery ready()

DOMContentLoaded dan window:load masing-masing memiliki peringatan. jQuery's ready()  memberikan solusi hybrid, menggunakan DOMContentLoaded bila memungkinkan, gagal ke window:load bila perlu, dan segera mengaktifkan callback jika DOM sudah selesai.

Anda dapat meneruskan handler siap Anda langsung ke jQuery sebagai $(handler), misalnya:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+xxx=" crossorigin="anonymous"></script>

<script>

  $(fungsi() {

    $("#test").klik(fungsi() {

      console.log("diklik:", ini);

    });

  });

</script>

<button id="test">klik saya</button>


Opsi 5: Delegasi event

Delegasikan penanganan event ke elemen selain target. Ketika sebuah elemen membuat sebuah event (asalkan itu adalah sebuah event yang bubbling dan tidak ada yang menghentikan propagasinya), setiap parent dalam nenek moyang elemen itu, sampai ke window browser, menerima event juga. Itu memungkinkan kita untuk melampirkan handler ke elemen yang ada dan kejadian sampel saat mereka muncul dari turunannya... bahkan dari turunan yang ditambahkan setelah handler dilampirkan. Yang harus kita lakukan adalah memeriksa event untuk melihat apakah itu dimunculkan oleh elemen yang diinginkan dan, jika demikian, jalankan kode kita.

Biasanya, pola ini digunakan pada suatu elemen yang tidak ada pada waktu awal dokuman html siap dibuka atau untuk menghindari pemasangan penangan proses dalam jumlah besar. Untuk efisiensi, pilih leluhur terdekat yang dapat diandalkan dari elemen target daripada melampirkannya ke dokumen.


JavaScript Native

<div id="ancestor"><!-- ancestor terdekat tersedia untuk skrip kami -->

  <script>

    document.getElementById("ancestor").addEventListener("click", function(e) {

      if (e.target.id === "keturunan") {

        console.log("diklik:", e.target);

      }

    });

  </script>

  <button id="descendant">klik saya</button>

</div>


jQuery on()

jQuery membuat fungsi yang baru dapat dijalankan melalui trigger tertentu ditandai dengan on(). Diberi nama event, proses dijalankan untuk turunan yang diinginkan, dan pengendali event, ini akan menyelesaikan penanganan event yang didelegasikan dan mengelola konteks ini:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-xxx=" crossorigin="anonymous"></script>

<div id="ancestor"><!-- ancestor terdekat tersedia untuk skrip kami -->

  <skrip>

    $("#leluhur").on("klik", "#keturunan", function(e) {

      console.log("diklik:", ini);

    });

  </skrip>

  <button id="descendant">klik saya</button>

</div>

Demikian tulisan kali ini, semoga bermanfaat.

logoblog

Tidak ada komentar:

Posting Komentar