Belajar dengan membaca secara berurutan

Membuat, Mengubah, dan Menghapus Element — createElement / classList / remove

Membahas createElement dan append untuk menambahkan element, remove untuk menghapusnya, classList dan dataset untuk class dan atribut, serta textContent untuk menampilkan input sebagai teks.

Kalau setiap perubahan, seperti menambah satu item ke daftar, menandai item selesai, atau menghapus satu item, kamu lakukan dengan meng-assign innerHTML, li yang seharusnya tetap juga ikut dibuat ulang. Kalau input pengguna di-assign dengan cara yang sama, tag yang terselip di dalamnya, seperti <a>, juga ikut menjadi element.

Artikel ini membahas cara membuat dan menghapus element, classList dan dataset untuk mengubah class dan atribut, serta cara memasukkan input sebagai teks apa adanya.

Membuat dan Menambahkan Element — createElement dan append

Anggap kamu ingin menambahkan "Kirim invoice" ke akhir daftar tugas. Kalau kamu menyambung string ke innerHTML lalu meng-assign-nya kembali, semua li yang sudah ada juga dibuat ulang sebagai element baru. li yang sebelumnya kamu simpan di variabel lewat querySelector masih menunjuk element lama yang sudah tidak ada di halaman, jadi mengubah teks lewat variabel itu tidak mengubah tampilan.

createElement (method yang menerima nama tag dan membuat element baru yang belum ada di mana pun di DOM tree) dipanggil seperti document.createElement("li"). Element yang dibuat baru menjadi bagian halaman setelah ditambahkan ke parent element dengan append (method yang menambahkan element yang diberikan sebagai child terakhir dari element yang memanggilnya).

document.body.innerHTML = `<ul id="tasks"><li>Buat penawaran harga</li><li>Bagikan notulen rapat</li></ul>`;
const taskList = document.querySelector("#tasks");

// Buat element li dan isi teksnya (belum ada di halaman)
const newTask = document.createElement("li");
newTask.textContent = "Kirim invoice";
console.log(newTask.outerHTML);                        // <li>Kirim invoice</li>
console.log(document.querySelectorAll("li").length);   // 2

// Setelah ditambahkan sebagai child terakhir ul, li menjadi bagian halaman
taskList.append(newTask);
console.log(document.querySelectorAll("li").length);   // 3
console.log(taskList.outerHTML);
// <ul id="tasks"><li>Buat penawaran harga</li><li>Bagikan notulen rapat</li><li>Kirim invoice</li></ul>
Kapan li Baru Masuk ke Halaman
createElement("li")newTask.textContent ="Kirim invoice"taskList.append(newTask)<li></li> dibuat;di halaman masih 2<li>Kiriminvoice</li>belum di halamanMasuk ke akhir ul;kini 3 li
Setelah baris createElement dan textContent, li di halaman masih 2. Jumlahnya baru bertambah di baris yang memanggil append.

Variabel newTask menunjuk element li yang sama, baik sebelum maupun sesudah append. Jadi kalau kamu meng-assign newTask.textContent setelah memanggil append, teks li ketiga di halaman yang berubah.

Tambahkan sekaligus pertanyaan pelanggan yang baru masuk ke daftar pertanyaan yang menunggu ditangani. Element ul daftarnya, inquiryList, dan array berisi subjek pertanyaan, newInquiries, sudah dideklarasikan.

① Jadikan setiap subjek di array sebagai element li, lalu tambahkan ke akhir daftar.

② Tampilkan jumlah li yang ada di halaman.

③ Tampilkan HTML daftar, termasuk tag element ul itu sendiri.

(Kalau berjalan dengan benar, penjelasan akan muncul.)

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menandai Tugas Selesai — classList dan dataset

Berikutnya, kamu ingin menambahkan class done ke tugas yang sudah selesai supaya CSS menampilkannya dengan coretan. Atribut class li itu berisi satu string, task urgent, jadi kalau kamu menimpanya dengan done, class task yang dipakai CSS untuk mengatur tampilan baris juga ikut hilang.

classList (object untuk mengelola class sebuah element per kata) punya add untuk menambah kata, remove untuk membuangnya, dan toggle yang menambahkannya kalau belum ada atau membuangnya kalau sudah ada. Atribut selain class ditulis dengan setAttribute(nama, nilai), sedangkan atribut yang diawali data- ditulis lewat dataset (object untuk membaca dan menulis atribut data berdasarkan namanya).

document.body.innerHTML = `<ul><li class="task urgent" data-id="T-1">Buat penawaran harga</li><li class="task urgent" data-id="T-2">Kirim invoice</li></ul>`;
const quote = document.querySelector('[data-id="T-1"]');
const invoice = document.querySelector('[data-id="T-2"]');

// classList menambah dan membuang per kata (class lain tetap ada)
quote.classList.add("done");
console.log(quote.outerHTML);    // <li class="task urgent done" data-id="T-1">Buat penawaran harga</li>
quote.classList.toggle("urgent");   // Sudah selesai, jadi buang urgent (karena ada, toggle membuangnya)
console.log(quote.outerHTML);    // <li class="task done" data-id="T-1">Buat penawaran harga</li>

// setAttribute mengganti seluruh value-nya (kalau dipakai untuk class, task ikut hilang)
invoice.setAttribute("class", "done");
console.log(invoice.outerHTML);  // <li class="done" data-id="T-2">Kirim invoice</li>

// Atribut yang diawali data- ditulis lewat dataset (doneAt menjadi data-done-at)
invoice.dataset.doneAt = "9/10";
console.log(invoice.outerHTML);
// <li class="done" data-id="T-2" data-done-at="9/10">Kirim invoice</li>
add Menambah, setAttribute Mengganti
quote.classList.add("done")Menambah kata doneke task urgentclass-nyatask urgent doneTampilan baristask tetap adainvoice.setAttribute("class", "done")Mengganti seluruhvalue classclass-nyahanya doneTampilan baristask hilang
add mempertahankan 2 kata dan menambah satu lagi, sedangkan setAttribute mengganti value-nya dengan done. Untuk menambah class, pakai classList.

Nama yang dipakai di dataset adalah nama atribut tanpa data-, dengan huruf setelah setiap tanda hubung yang tersisa dijadikan huruf kapital. data-id dibaca dan ditulis sebagai dataset.id, data-done-at sebagai dataset.doneAt, dan saat di-assign, atributnya ditulis ke HTML dengan nama aslinya.

dataset Tidak Menerima Nama dengan Tanda Hubung

Kalau kamu membaca dengan tanda hubung yang masih ada, seperti dataset["done-at"], hasilnya undefined, bukan error, jadi salah tulisnya mudah terlewat. Kalau di-assign dengan cara itu, baris tersebut melempar error. Nama error-nya SyntaxError, tapi berbeda dengan kesalahan sintaks di kode, error ini terjadi saat kode dijalankan, jadi baris-baris sebelumnya tetap dijalankan.

Perbarui class done di checklist onboarding karyawan baru. HTML daftarnya sudah disiapkan.

① Tambahkan class done ke item C-2.

② Item C-1 keliru ditandai selesai. Ubah class done-nya dengan satu kali pemanggilan method.

③ Tulis atribut data tanggal selesai di item C-2.

④ Tampilkan HTML daftar, termasuk tag element ul itu sendiri.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menghapus Element — remove dan Referensi yang Tersisa di Variabel

Sekarang misalkan kamu ingin mengeluarkan tugas yang sudah selesai dari daftar. Kalau daftarnya kamu tulis ulang dengan innerHTML, class dan atribut data yang ditambahkan di bagian sebelumnya juga harus ditulis ulang ke string HTML, dan kalau ada satu saja yang terlewat, tugas yang tersisa kehilangan tanda selesainya.

remove (method yang melepas element pemanggilnya dari parent dan menghapusnya dari DOM tree) dipanggil tanpa argument pada element yang ingin dihapus, seperti doneItem.remove(). classList.remove("done") di bagian sebelumnya hanya membuang satu kata dari class; method itu berbeda dengan method ini, yang menghapus element-nya sendiri.

document.body.innerHTML = `<ul id="tasks"><li data-id="T-1">Buat penawaran harga</li><li data-id="T-2" class="done">Kirim invoice</li><li data-id="T-3">Bagikan notulen rapat</li></ul>`;
const tasks = document.querySelectorAll("li");

// Cari li yang sudah selesai, lalu hapus dari DOM tree
const doneItem = document.querySelector(".done");
doneItem.remove();
console.log(document.querySelectorAll("li").length);   // 2

// Element yang dihapus dan NodeList yang diambil sebelumnya tetap ada di variabelnya
console.log(doneItem.textContent);                     // Kirim invoice
console.log(tasks.length);                             // 3 (element yang ditemukan saat itu)

// Masih ada di variabel, jadi append bisa mengembalikannya ke akhir daftar
document.querySelector("#tasks").append(doneItem);
console.log(document.querySelectorAll("li").length);   // 3
Jumlah dari Pencarian Ulang vs Jumlah yang Tersimpan
querySelectorAll("li") lagiMencari di DOMsetelah removeli T-1dan T-3length-nya 2tasks, diambilsebelum removeIsi sama sepertisaat diambilli T-1, T-2,dan T-3length-nya 3
Pencarian ulang setelah remove hanya menemukan T-1 dan T-3, sedangkan tasks tetap berisi 3. Untuk mengecek jumlahnya, cari ulang.

querySelectorAll hanya mengembalikan element yang ditemukan saat dipanggil; perubahan DOM setelahnya tidak diikuti. doneItem yang sudah dihapus juga tetap ada di variabelnya, jadi teksnya masih bisa dibaca, atau element-nya dikembalikan ke daftar dengan append.

Di layar penulisan email, hapus sekaligus semua lampiran yang dibatalkan dari daftar. HTML daftarnya dan element ul-nya, attachmentList, sudah disiapkan.

① Ambil semua element file yang dibatalkan, lalu hapus dari daftar satu per satu.

② Setelah dihapus, tampilkan jumlah element yang diambil di ①.

③ Ambil lagi element file yang dibatalkan, lalu tampilkan jumlahnya.

④ Tampilkan HTML daftar, termasuk tag element ul itu sendiri.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menampilkan Input sebagai Teks — textContent dan innerHTML

Bayangkan kolom ulasan produk yang menampilkan komentar kiriman pengguna. Komentar itu disimpan, dan string yang sama juga tampil di halaman pengunjung lain. Kalau komentarnya berisi tag a (tag untuk membuat link, dengan tujuan link ditulis di atribut href), meng-assign-nya ke innerHTML membuat link palsu yang dipasang pengirimnya tampil sebagai link sungguhan.

String yang di-assign ke innerHTML di-parse sebagai HTML, dan tag di dalamnya menjadi element. String yang di-assign ke textContent tidak di-parse, jadi < pun masuk sebagai karakter biasa. Memasukkan input ke innerHTML bukan cuma membuka jalan untuk link palsu, tapi juga bisa menjadi penyebab XSS (celah keamanan di mana kode yang diselipkan pengguna ke input dijalankan di halaman pengunjung lain).

document.body.innerHTML = `<p class="review"></p>`;
const review = document.querySelector(".review");
// String yang diketik pengguna di kolom ulasan (terselip link palsu)
const reviewText = '<a href="https://example.com/login">Login ulang</a> untuk melanjutkan';

// Kalau dimasukkan ke innerHTML, tag a menjadi element a sungguhan
review.innerHTML = reviewText;
console.log(document.querySelectorAll("a").length);   // 1

// Kalau dimasukkan ke textContent, tag-nya juga masuk sebagai teks biasa
review.textContent = reviewText;
console.log(document.querySelectorAll("a").length);   // 0
console.log(review.outerHTML);
// <p class="review">&lt;a href="https://example.com/login"&gt;Login ulang&lt;/a&gt; untuk melanjutkan</p>
Isi p Setelah Diberi Input yang Sama
p setelah innerHTML di-assign
Element a — href-nya example.com/login
  • Teks di dalamnya "Login ulang"
  • Kalau diklik, pindah ke situs lain
Teks — untuk melanjutkan
  • Menyusul setelah element a
p setelah textContent di-assign
Teks — seluruh input jadi satu
  • <a href="…">Login ulang</a> untuk melanjutkan
  • Tidak ada element a
Dengan innerHTML, tag a menjadi element; dengan textContent, tag itu tetap berupa teks. Yang mencegah input menjadi element adalah textContent.

&lt; dan &gt; di outerHTML adalah cara HTML menulis < dan > sebagai teks. Kalau dibaca lagi dengan textContent, hasilnya kembali menjadi karakter aslinya. Tabel di bawah merangkum cara mengubah element yang dibahas di artikel ini, dikelompokkan berdasarkan bagian yang diubah.

Yang diubahCara menulisPerhatikan
Element itu sendiricreateElement / append / removeBelum di halaman sebelum append
classclassList.add / remove / togglesetAttribute mengganti seluruh value
Atribut berawalan data-dataset.doneAt = "9/10"Tanpa data-, huruf setelah - jadi kapital
Atribut lainnyasetAttribute("href", "/tasks/T-2")Ditambah, atau value-nya diganti
Isi tekstextContentInput pengguna masuk ke sini
Isi HTMLinnerHTMLHanya HTML yang kamu tulis sendiri

Kode di onerror milik img Tetap Berjalan

<script> yang dimasukkan ke innerHTML tidak dijalankan, tapi kalau tag img, yang menampilkan gambar, ditulis sebagai <img src="x" onerror="…">, onerror (atribut berisi kode yang dijalankan saat gambar gagal dimuat) tetap berjalan. Jadi, meskipun <script> tidak dijalankan, input tetap tidak aman dimasukkan ke innerHTML.

Tampilkan satu kiriman di kolom ulasan produk. Nama pengirim author, komentar comment, dan element kolomnya reviewArea sudah dideklarasikan.

① Buat element article, lalu tambahkan ke dalamnya element strong berisi nama pengirim dan element p berisi komentar, sesuai urutan itu. Masukkan input sebagai teks apa adanya.

② Tambahkan article ke kolom ulasan, lalu tampilkan jumlah element a di halaman.

③ Tampilkan HTML-nya, termasuk tag element article itu sendiri.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Tepat setelah const li = document.createElement("li");, di mana posisi li di halaman?

Soal 2Kalau class sebuah li adalah task urgent, apa class-nya setelah setAttribute("class", "done")?

Soal 3Setelah p.textContent = "<b>Baru</b>";, ada berapa element b di dalam p?