Masukkan Password
69 Cineflix: Render Semua Film
Lecture ini sangat penting, karena untuk pertama kalinya kita mulai melihat bagaimana method yang sebelumnya kamu pelajari secara terpisah dipakai dalam project nyata.
Fokus utama lecture ini adalah:
Mengambil data dari
moviesarray β melakukan looping denganforEach()β membuat HTML card secara dinamis β memasukkan card tersebut ke DOM.
Kalau kamu memahami alur ini, kamu akan jauh lebih siap untuk fitur berikutnya seperti search, filter, sort, delete, dan create movie.
1. Tujuan lecture ini
Pada lecture sebelumnya kita sudah punya:
let movies = [
{...},
{...},
{...},
{...},
{...}
];
Artinya kita mempunyai 5 object movie.
Sekarang masalahnya:
Bagaimana caranya supaya kelima movie tersebut muncul di halaman web?
Awalnya HTML kita kosong:
<section id="movie-list-container">
</section>
Yang kita inginkan:
movies array
β
JavaScript membaca data
β
loop setiap movie
β
buat HTML card
β
masukkan card ke DOM
β
browser menampilkan
Hasil akhirnya:
ββββββββββββββββ ββββββββββββββββ
β Movie 1 β β Movie 2 β
β Rating β β Rating β
β Genre β β Genre β
β Year β β Year β
ββββββββββββββββ ββββββββββββββββ
ββββββββββββββββ ββββββββββββββββ
β Movie 3 β β Movie 4 β
β Rating β β Rating β
β Genre β β Genre β
β Year β β Year β
ββββββββββββββββ ββββββββββββββββ
ββββββββββββββββ
β Movie 5 β
β Rating β
β Genre β
β Year β
ββββββββββββββββ
2. Data movies adalah sumbernya
Misalkan kita punya data seperti ini:
let movies = [
{
id: 1,
name: "Movie A",
rating: 4.6,
description: "Description A",
genre: ["Action", "Sci-Fi", "Drama"],
image: "images/movie-a.jpg",
releaseYear: 2014
},
{
id: 2,
name: "Movie B",
rating: 2.7,
description: "Description B",
genre: ["Action", "Comedy"],
image: "",
releaseYear: 2018
}
];
Perhatikan bahwa movies adalah Array.
Di dalam array terdapat Object.
Dan di dalam object terdapat berbagai property.
movies ARRAY
β
βββ Movie Object
β βββ id
β βββ name
β βββ rating
β βββ description
β βββ genre β ARRAY
β βββ image
β βββ releaseYear
β
βββ Movie Object
β βββ id
β βββ name
β βββ rating
β βββ ...
β
βββ ...
3. Langkah pertama: mendapatkan tempat untuk movie
Di HTML terdapat:
<section id="movie-list-container">
</section>
Kita ingin memasukkan movie card ke dalam <section> ini.
Maka JavaScript perlu mendapatkan element tersebut.
let movieListSection = document.getElementById(
"movie-list-container"
);
Sekarang:
HTML
β
βββ <section id="movie-list-container">
β
β
getElementById()
β
β
movieListSection
movieListSection sekarang berisi referensi ke DOM element tersebut.
Jadi kita bisa memanipulasinya.
4. Kenapa menggunakan getElementById()?
Karena HTML memiliki:
id="movie-list-container"
Dan kita mengambilnya dengan:
document.getElementById("movie-list-container");
Perhatikan:
HTML
id="movie-list-container"
JavaScript
document.getElementById("movie-list-container");
Tidak menggunakan #.
Berbeda dengan querySelector():
document.querySelector("#movie-list-container");
Keduanya bisa digunakan.
5. Membuat function renderAllMovies()
Lecture kemudian membuat:
function renderAllMovies(movieList) {
...
}
Kenapa function ini menerima parameter movieList?
Karena kita ingin function-nya fleksibel.
Misalnya:
renderAllMovies(movies);
Artinya:
“Render semua movie yang ada di array
movies.”
Nanti kalau kita punya array hasil filtering:
let filteredMovies = ...
kita juga bisa:
renderAllMovies(filteredMovies);
Jadi function tidak harus selalu bekerja dengan variable global movies.
Ini desain function yang bagus.
6. renderAllMovies(movies)
Saat halaman pertama kali dibuka:
renderAllMovies(movies);
Terjadi:
movies
β
β
renderAllMovies(movies)
β
β
movieList parameter
Jadi di dalam function:
function renderAllMovies(movieList) {
movieList sekarang mengacu ke array movies.
7. Bagian terpenting: forEach()
Di dalam function:
movieList.forEach((movie) => {
...
});
Ini adalah inti lecture.
Ingat materi kita sebelumnya:
forEach()digunakan untuk menjalankan suatu function satu kali untuk setiap element dalam array.
Misalnya:
let names = ["John", "Mark", "Steve"];
names.forEach((name) => {
console.log(name);
});
Hasil:
John
Mark
Steve
Karena array mempunyai 3 element, callback dijalankan 3 kali.
8. Dalam project ini forEach() bekerja bagaimana?
Misalnya ada:
movies = [
movie1,
movie2,
movie3,
movie4,
movie5
];
Kemudian:
movies.forEach((movie) => {
...
});
Maka secara mental:
Iteration 1
movie = movie1
β
buat card movie1
Iteration 2
movie = movie2
β
buat card movie2
Iteration 3
movie = movie3
β
buat card movie3
Iteration 4
movie = movie4
β
buat card movie4
Iteration 5
movie = movie5
β
buat card movie5
Jadi forEach() adalah seperti:
“Untuk setiap movie, lakukan pekerjaan berikut.”
9. Callback function
Kode:
movieList.forEach((movie) => {
...
});
Bagian:
(movie) => {
...
}
adalah callback function.
forEach() akan memanggil function tersebut satu per satu.
Jadi:
forEach()
β
βββ panggil callback untuk movie 1
βββ panggil callback untuk movie 2
βββ panggil callback untuk movie 3
βββ panggil callback untuk movie 4
βββ panggil callback untuk movie 5
10. Apa isi parameter movie?
Ini sangat penting.
Ketika iteration pertama:
movie
berisi object movie pertama.
Misalnya:
{
id: 1,
name: "Movie A",
rating: 4.6,
...
}
Maka:
movie.name
menghasilkan:
Movie A
Iteration kedua:
movie.name
menghasilkan:
Movie B
dan seterusnya.
Jadi movie bukan nama array.
movie adalah satu object movie yang sedang diproses.
11. forEach() sebenarnya memberikan 3 argument
Secara lengkap:
movieList.forEach((movie, index, array) => {
...
});
Ada tiga:
movie β element saat ini
index β index saat ini
array β array asli
Misalnya:
movies.forEach((movie, index, array) => {
console.log(movie);
console.log(index);
console.log(array);
});
Untuk movie pertama:
movie β object movie pertama
index β 0
array β movies
Untuk movie kedua:
movie β object movie kedua
index β 1
array β movies
dan seterusnya.
12. Kenapa lecture hanya menggunakan movie?
Karena kode yang sedang dibuat tidak membutuhkan:
index
dan:
array
Jadi cukup:
movieList.forEach((movie) => {
Ini lebih bersih.
13. Sekarang membuat movie card
Di setiap iteration:
let movieCard = `...`;
Perhatikan menggunakan:
` `
yaitu backtick.
Bukan:
" "
atau:
' '
Kenapa?
Karena kita ingin menggunakan template literal.
14. Template literal
Misalnya:
let name = "John";
let html = `<h2>${name}</h2>`;
Hasil:
<h2>John</h2>
Bagian:
${name}
adalah JavaScript expression yang disisipkan ke dalam string.
15. Kenapa ini berguna untuk movie card?
Misalnya kita punya:
movie.name
Kita bisa membuat:
let movieCard = `
<h2>${movie.name}</h2>
`;
Kalau:
movie.name = "Inception"
hasil string menjadi:
<h2>Inception</h2>
Kalau movie berikutnya:
movie.name = "Avatar"
hasilnya menjadi:
<h2>Avatar</h2>
Jadi satu template bisa digunakan untuk banyak movie.
16. Kenapa harus backtick?
Ini penting.
Yang bisa menggunakan:
${...}
adalah template literal, yaitu menggunakan backtick:
`Hello ${name}`
Bukan:
"Hello ${name}"
dan bukan:
'Hello ${name}'
Contoh:
let name = "John";
console.log(`Hello ${name}`);
hasil:
Hello John
Sedangkan:
console.log("Hello ${name}");
hasil:
Hello ${name}
17. Sekarang kita membuat HTML card lengkap
Misalnya template-nya:
let movieCard = `
<div class="movie-card">
<h2>${movie.name}</h2>
<p>${movie.description}</p>
<p>${movie.genre}</p>
<p>${movie.releaseYear}</p>
<p>${movie.rating}</p>
</div>
`;
Perhatikan setiap data berasal dari object:
movie.name
movie.description
movie.genre
movie.releaseYear
movie.rating
Jadi tidak ada lagi data hardcoded.
18. Apa yang terjadi pada setiap iteration?
Misalkan movie pertama:
{
name: "Movie A",
rating: 4.6,
description: "Description A",
genre: ["Action", "Sci-Fi"],
releaseYear: 2014
}
Maka:
`${movie.name}`
menjadi:
Movie A
dan:
`${movie.rating}`
menjadi:
4.6
dan:
`${movie.releaseYear}`
menjadi:
2014
Sehingga template menghasilkan HTML yang sudah berisi data Movie A.
19. Kemudian HTML tersebut dimasukkan ke DOM
Setelah membuat:
let movieCard = `...`;
kita masih punya masalah.
movieCard hanya sebuah String.
Misalnya:
console.log(movieCard);
isinya:
<div class="movie-card">
<h2>Movie A</h2>
...
</div>
Tapi string tersebut belum otomatis muncul di halaman.
Kita harus memasukkannya ke DOM.
20. Menggunakan insertAdjacentHTML()
Lecture menggunakan:
movieListSection.insertAdjacentHTML(
"beforeend",
movieCard
);
Method ini sangat penting.
Formatnya:
element.insertAdjacentHTML(position, htmlString);
Di sini:
movieListSection
adalah tempat kita memasukkan HTML.
Sedangkan:
movieCard
adalah HTML string yang ingin dimasukkan.
21. Apa arti "beforeend"?
Ini sering membingungkan di awal.
Bayangkan:
<section id="movie-list-container">
</section>
Ada posisi-posisi:
section
βββββββββββββββββββ
beforebegin β β
β β
afterbegin β β
β β
β β
beforeend β β
βββββββββββββββββββ
afterend β
Untuk:
insertAdjacentHTML("beforeend", movieCard)
artinya:
Masukkan HTML di dalam element, tepat sebelum closing tag.
Sebelum:
<section id="movie-list-container">
</section>
Setelah memasukkan card:
<section id="movie-list-container">
<div class="movie-card">
...
</div>
</section>
Jadi beforeend sangat cocok untuk menambahkan item ke akhir container.
22. Kenapa bukan innerHTML?
Kita sebenarnya bisa saja:
movieListSection.innerHTML += movieCard;
Tetapi lecture menggunakan:
insertAdjacentHTML("beforeend", movieCard);
Kelebihannya untuk kasus seperti ini adalah kita bisa menambahkan HTML di posisi tertentu tanpa menulis ulang seluruh innerHTML container.
Untuk sekarang cukup pahami:
innerHTML
β membaca/mengganti isi HTML
insertAdjacentHTML
β menyisipkan HTML string pada posisi tertentu
23. Alur lengkap satu movie
Sekarang mari gabungkan semuanya.
movies array
β
forEach()
β
ambil satu movie object
β
movie.name
movie.rating
movie.description
movie.genre
movie.releaseYear
β
template literal
β
buat movieCard HTML string
β
insertAdjacentHTML()
β
movie-list-section
β
browser menampilkan card
24. Alur untuk 5 movie
Karena ada 5 movie:
movies
β
βββ Movie 1
β β
β buat card
β β
β insert
β
βββ Movie 2
β β
β buat card
β β
β insert
β
βββ Movie 3
β β
β buat card
β β
β insert
β
βββ Movie 4
β β
β buat card
β β
β insert
β
βββ Movie 5
β
buat card
β
insert
Akhirnya:
movie-list-container
β
βββ card movie 1
βββ card movie 2
βββ card movie 3
βββ card movie 4
βββ card movie 5
25. Kenapa awalnya hanya h2?
Lecture pertama-tama mencoba sesuatu yang sangat sederhana:
let movieCard = `<h2>${movie.name}</h2>`;
Tujuannya bukan langsung membuat UI sempurna.
Tujuannya untuk memastikan:
βApakah kita berhasil melakukan looping dan memasukkan data ke DOM?β
Kalau hasilnya:
Movie A
Movie B
Movie C
Movie D
Movie E
berarti mekanismenya sudah berhasil.
Setelah itu baru HTML-nya diperbesar menjadi card lengkap.
Ini adalah cara debugging/building yang bagus:
buat sederhana
β
pastikan bekerja
β
tambahkan kompleksitas
26. Kenapa semua movie awalnya muncul satu baris?
Lecture menemukan bahwa movie names muncul seperti:
Movie A Movie B Movie C Movie D Movie E
padahal menggunakan:
<h2>
yang biasanya block-level element.
Penyebabnya adalah CSS.
Container memiliki:
display: flex;
Flexbox secara default mengatur child dalam satu baris:
βββββββββββββββββββββββββββββββββββββ
β Movie A | Movie B | Movie C | ... β
βββββββββββββββββββββββββββββββββββββ
Jadi ini bukan masalah forEach().
Bukan juga masalah <h2>.
Ini akibat CSS layout.
27. Hardcoded vs dynamic
Ini bagian yang sangat penting.
Sebelumnya HTML card mungkin seperti:
<h2>Movie A</h2>
<p>Some description</p>
<p>Action</p>
<p>2014</p>
<p>4.6</p>
Semua nilai ditulis manual.
Ini disebut:
hardcoded
Masalahnya kalau punya 100 movie, kita harus membuat 100 HTML secara manual.
Sekarang:
<h2>${movie.name}</h2>
<p>${movie.description}</p>
<p>${movie.genre}</p>
<p>${movie.releaseYear}</p>
<p>${movie.rating}</p>
Data berasal dari object.
Ini:
dynamic rendering
Satu template bisa digunakan untuk berapa pun jumlah movie.
28. Perhatikan genre
Ada satu hal menarik.
Misalnya:
genre: ["Action", "Sci-Fi", "Drama"]
Kemudian:
${movie.genre}
Ketika array dimasukkan ke String, biasanya akan tampil seperti:
Action,Sci-Fi,Drama
Karena array dikonversi ke String.
Kalau ingin tampil lebih bagus:
${movie.genre.join(", ")}
hasil:
Action, Sci-Fi, Drama
Kemungkinan nanti project akan melakukan formatting seperti ini.
Ini contoh bagus bahwa:
Array methods dan String operations bisa bekerja bersama.
29. movie.image
Lecture juga menambahkan:
${movie.image}
ke atribut gambar.
Misalnya:
<img src="${movie.image}">
Kalau:
movie.image = "images/movie1.jpg";
hasil HTML:
<img src="images/movie1.jpg">
Browser kemudian mencari file gambar tersebut.
30. Bagaimana dengan image yang kosong?
Misalnya:
movie.image = "";
Maka:
<img src="">
tidak menghasilkan gambar yang kita inginkan.
Lecture belum menyelesaikan masalah ini.
Untuk sementara:
image tersedia
β
tampilkan image
image kosong
β
belum ditangani
Lecture berikutnya akan membahas formatting dan kemungkinan default image.
31. Satu hal yang sangat penting: forEach() tidak membuat array baru
Ingat karakteristik forEach().
movies.forEach((movie) => {
...
});
Tujuannya:
menjalankan logic untuk setiap element.
Bukan:
membuat array baru.
Misalnya:
let result = movies.forEach(...);
result biasanya menjadi:
undefined
Kalau tujuan kita adalah membuat array baru, biasanya kita akan mempelajari:
map()
Kalau tujuan kita menyaring:
filter()
Kalau mencari satu:
find()
Jadi:
forEach()
β lakukan sesuatu untuk setiap element
Dan di project ini:
“Untuk setiap movie, buat card dan tampilkan.”
32. Kenapa forEach() cocok untuk render?
Karena requirement-nya memang:
Setiap movie harus dibuatkan satu card.
Misalnya:
1 movie β 1 card
5 movie β 5 card
100 movie β 100 card
Itulah pola:
movies.forEach((movie) => {
createCard(movie);
});
33. Hubungkan dengan konsep callback yang sudah dipelajari
Sebelumnya kamu sudah belajar:
setTimeout(function() {
console.log("Hello");
}, 1000);
Function yang diberikan ke setTimeout() adalah callback.
Sekarang:
movies.forEach((movie) => {
...
});
Arrow function tersebut juga callback.
Jadi konsep callback yang dulu terlihat abstrak sekarang punya kegunaan nyata.
forEach()
β
menerima function
β
memanggil function tersebut
β
untuk setiap movie
34. Bagian kode secara konsep
Strukturnya kira-kira:
let movieListSection =
document.getElementById("movie-list-container");
function renderAllMovies(movieList) {
movieList.forEach((movie) => {
let movieCard = `
<div class="movie-card">
<h2>${movie.name}</h2>
<p>${movie.description}</p>
<p>${movie.genre}</p>
<p>${movie.releaseYear}</p>
<p>${movie.rating}</p>
</div>
`;
movieListSection.insertAdjacentHTML(
"beforeend",
movieCard
);
});
}
renderAllMovies(movies);
Tidak perlu menghafal kode ini sekarang. Yang lebih penting adalah alur pikirnya.
35. Baca kode tersebut seperti manusia
Daripada membaca:
movieList.forEach((movie) => {
sebagai syntax yang rumit, bacalah:
βUntuk setiap movie yang ada di movieList…β
Kemudian:
let movieCard = `...`;
baca:
βBuat HTML card berdasarkan movie tersebut.β
Kemudian:
movieListSection.insertAdjacentHTML(
"beforeend",
movieCard
);
baca:
βMasukkan card itu ke akhir movie list.β
Jadi keseluruhan:
Untuk setiap movie β buat card β masukkan card ke halaman.
Itulah inti lecture ini.
36. Connection dengan DOM yang sudah kamu pelajari
Kita sebelumnya belajar:
document.getElementById()
dan:
insertAdjacentElement()
Sekarang kita menggunakan:
insertAdjacentHTML()
Perbedaannya:
insertAdjacentElement()
Menerima Element object:
let div = document.createElement("div");
parent.insertAdjacentElement(
"beforeend",
div
);
insertAdjacentHTML()
Menerima HTML String:
let html = `<div>Hello</div>`;
parent.insertAdjacentHTML(
"beforeend",
html
);
Mental model:
insertAdjacentElement()
β
Element
insertAdjacentHTML()
β
HTML String
Dalam lecture ini kita memiliki:
let movieCard = `...`;
yang merupakan String berisi HTML.
Maka:
insertAdjacentHTML()
sangat cocok.
37. Connection dengan template literal
Ada tiga konsep yang bertemu di sini:
movie object
β
movie.name
β
template literal
β
HTML string
β
insertAdjacentHTML()
β
DOM
Contoh:
`<h2>${movie.name}</h2>`
Bukan sekadar String biasa.
String tersebut berisi HTML yang dibuat berdasarkan data.
38. Connection dengan array
Kita juga menggabungkan:
Array
β
forEach()
β
Object
β
property access
β
String
β
DOM
Lebih lengkap:
movies[]
β
forEach()
β
movie object
β
movie.name
movie.rating
movie.genre
movie.description
movie.releaseYear
β
template literal
β
HTML string
β
insertAdjacentHTML()
β
DOM
β
Browser UI
Ini sebenarnya adalah fondasi penting untuk dynamic web page.
39. Kenapa ini penting untuk fitur berikutnya?
Karena hampir semua fitur berikutnya akan berhubungan dengan renderAllMovies().
Misalnya search:
movies
β
search
β
filteredMovies
β
renderAllMovies(filteredMovies)
Filter genre:
movies
β
filter genre
β
filteredMovies
β
renderAllMovies(filteredMovies)
Delete:
movies
β
hapus movie
β
renderAllMovies(movies)
Create:
form
β
new movie object
β
movies.push(newMovie)
β
renderAllMovies(movies)
Jadi function:
renderAllMovies()
bisa menjadi salah satu function yang sangat penting dalam project.
40. Satu catatan teknis penting: render ulang
Ada satu hal yang perlu kamu waspadai saat memahami konsep ini.
Jika kita menjalankan:
renderAllMovies(movies);
kemudian menjalankannya lagi tanpa mengosongkan container:
renderAllMovies(movies);
maka movie bisa muncul dua kali.
Karena:
insertAdjacentHTML("beforeend", ...)
artinya:
tambahkan ke akhir, bukan replace isi lama.
Contoh:
Awalnya:
Movie 1
Movie 2
render lagi:
Movie 1
Movie 2
Movie 1
Movie 2
Jadi biasanya sebelum render ulang kita perlu memikirkan strategi seperti:
movieListSection.innerHTML = "";
lalu render lagi.
Ini akan menjadi konsep penting ketika nanti melakukan search, filter, sorting, create, dan delete.
41. Kesalahan mental yang sebaiknya dihindari
β Salah:
movieadalah array movies.
β Benar:
movieList β array
movie β satu element/object dari array
β Salah:
movieCardadalah HTML element.
β Dalam kode lecture:
let movieCard = `...`;
movieCard adalah String yang berisi HTML.
β Salah:
forEach()mengubah array menjadi HTML.
β Lebih tepat:
forEach() menjalankan callback untuk setiap element, dan di dalam callback-lah kita membuat HTML.
β Salah:
insertAdjacentHTML()membuat movie object.
β Benar:
Method itu memasukkan HTML string ke DOM.
42. Ringkasan setiap bagian
| Kode/konsep | Artinya |
|---|---|
movies | array semua movie |
movieList | parameter yang menerima array movie |
forEach() | proses setiap movie |
movie | satu movie object saat iteration |
movie.name | nama movie |
movie.rating | rating |
movie.genre | genre |
movie.description | deskripsi |
movie.releaseYear | tahun rilis |
`${...}` | memasukkan JS expression ke template literal |
movieCard | HTML string untuk satu card |
insertAdjacentHTML() | memasukkan HTML string ke DOM |
"beforeend" | tambahkan di akhir isi element |
43. Mental model terakhir π
Simpan diagram ini karena ini akan sangat membantu untuk lecture berikutnya:
movies ARRAY
β
β
renderAllMovies()
β
β
forEach()
β
βββββββββββββ΄ββββββββββββ
β β
movie 1 movie 2
β β
movie.name movie.name
movie.rating movie.rating
movie.genre movie.genre
β β
Template Literal Template Literal
β β
HTML String HTML String
β β
insertAdjacentHTML() insertAdjacentHTML()
β β
Movie Card Movie Card
βββββββββββββ¬ββββββββββββ
β
DOM
β
Browser UI
Atau kalau dibuat super sederhana:
DATA
β
movies[]
β
forEach()
β
1 movie
β
buat HTML
β
insert ke DOM
β
CARD
Kalimat yang paling penting dari lecture ini:
π§
forEach()dipakai karena kita ingin melakukan sesuatu untuk setiap movie. Dalam kasus ini, untuk setiap movie kita membuat satu HTML card dan memasukkannya ke UI.
Dan ini adalah langkah pertama menuju aplikasi yang benar-benar dynamic, bukan lagi HTML yang semua datanya hardcoded.
Saya juga bisa membuat gambar yang menjelaskan alur movies β forEach β template literal β DOM β movie card secara visual.