Masukkan Password
77 Cineflix: Menampilkan Detail Film
Lecture ini cukup penting karena mulai menggabungkan event + function + find() + template literal + DOM manipulation menjadi satu fitur nyata: ketika user menekan tombol Details, aplikasi mencari film yang dipilih lalu menampilkan detail film tersebut di modal.
1. Gambaran besar fitur yang dibuat
Sebelumnya kita sudah punya banyak movie card:
┌──────────────────────────────┐
│ Interstellar │
│ ★★★★★ │
│ ... │
│ [ Details ] │
└──────────────────────────────┘
┌──────────────────────────────┐
│ Fast & Furious │
│ ★★★★☆ │
│ ... │
│ [ Details ] │
└──────────────────────────────┘
Sekarang ketika user klik:
Fast & Furious
↓
[ Details ]
↓
showMovieDetails(movie.id)
↓
cari movie berdasarkan ID
↓
dapat object Fast & Furious
↓
buat HTML detail
↓
masukkan HTML ke modal
↓
tampilkan modal
Jadi inti lecture ini adalah:
Klik tombol → kirim ID movie → cari movie → buat HTML → tampilkan di modal.
2. Kenapa menggunakan ID movie?
Misalnya array movies kita seperti ini:
let movies = [
{
id: 1,
name: "Interstellar",
rating: 4.6,
genre: ["sci-fi", "drama"]
},
{
id: 2,
name: "Fast and Furious",
rating: 4.2,
genre: ["action"]
},
{
id: 3,
name: "Inception",
rating: 4.5,
genre: ["sci-fi", "thriller"]
}
];
Setiap movie punya:
id
yang berbeda.
Contohnya:
Interstellar → id 1
Fast and Furious → id 2
Inception → id 3
Ketika user menekan tombol Details milik Fast and Furious, kita cukup mengirim:
2
Kemudian JavaScript bisa berkata:
“Cari movie yang
id-nya 2.”
Hasilnya:
{
id: 2,
name: "Fast and Furious",
rating: 4.2,
genre: ["action"]
}
Movie inilah yang disebut:
selectedMovie
3. Langkah pertama: menampilkan modal
Lecture membuat function:
function showMovieDetailsModal() {
let movieDetailsSection =
document.getElementById("movie-details-container");
movieDetailsSection.classList.remove("hidden");
}
Mari kita pecah.
Ambil element
document.getElementById("movie-details-container");
Artinya:
“Cari element HTML yang mempunyai ID
movie-details-container.”
Misalnya HTML:
<div id="movie-details-container" class="hidden">
...
</div>
Hasil dari:
document.getElementById(...)
adalah object DOM element tersebut.
4. Kenapa menggunakan classList.remove()?
Pada awal halaman:
<div id="movie-details-container" class="hidden">
CSS:
.hidden {
display: none;
}
Jadi:
hidden
↓
display: none
↓
modal tidak terlihat
Ketika Details diklik:
movieDetailsSection.classList.remove("hidden");
Maka:
class hidden dihapus
↓
display:none hilang
↓
modal terlihat
Jadi:
classList.remove("hidden")
berarti:
“Hapus class
hiddendari element.”
5. Function untuk menyembunyikan modal
Kebalikannya:
function hideMovieDetailsModal() {
let movieDetailsSection =
document.getElementById("movie-details-container");
movieDetailsSection.classList.add("hidden");
}
Sekarang:
showMovieDetailsModal()
↓
remove("hidden")
↓
modal muncul
Sedangkan:
hideMovieDetailsModal()
↓
add("hidden")
↓
modal menghilang
Ini pola yang sangat umum dalam JavaScript DOM.
6. Function utama: showMovieDetails()
Sekarang kita membutuhkan function yang benar-benar mencari movie.
function showMovieDetails(movieId) {
showMovieDetailsModal();
// cari movie
}
Perhatikan:
movieId
adalah parameter.
Misalnya kita memanggil:
showMovieDetails(2);
maka:
movieId = 2
7. Bagaimana tombol Details memanggil function?
Pada card movie, lecture menggunakan inline event handler.
Kurang lebih:
<button onclick="showMovieDetails(${movie.id})">
Details
</button>
Misalnya movie:
{
id: 2,
name: "Fast and Furious"
}
maka template literal menghasilkan:
<button onclick="showMovieDetails(2)">
Details
</button>
Ketika diklik:
Click Details
↓
showMovieDetails(2)
Untuk Interstellar misalnya:
<button onclick="showMovieDetails(1)">
Details
</button>
maka:
Click Details
↓
showMovieDetails(1)
Jadi setiap tombol membawa ID movie masing-masing.
8. Kenapa tidak langsung mengirim object movie?
Ini bagian yang agak membingungkan dari lecture.
Misalnya kita ingin melakukan:
onclick="showMovieDetails(movie)"
Masalahnya adalah onclick di HTML tidak secara otomatis memahami variable JavaScript movie yang merupakan object dari callback forEach().
Contoh object:
{
id: 2,
name: "Fast and Furious",
rating: 4.2
}
HTML inline handler bukan tempat yang baik untuk membawa object JavaScript seperti itu.
Sebaliknya:
onclick="showMovieDetails(2)"
jauh lebih sederhana.
Kita mengirim nilai sederhana:
2
kemudian JavaScript mencari object berdasarkan ID tersebut.
Mental model
HTML
│
│ kirim ID
↓
showMovieDetails(2)
│
│ cari di JavaScript
↓
movies.find(...)
│
↓
movie object
Ini juga membuat tombol HTML tetap sederhana.
9. Mencari movie dengan find()
Sekarang bagian paling penting.
Kita punya:
movies
dan kita punya:
movieId
Kita ingin mencari movie dengan ID tersebut.
Gunakan:
let selectedMovie = movies.find((movie) => {
return movie.id === movieId;
});
Mari kita pahami perlahan.
10. Apa itu find()?
find() adalah method Array yang digunakan untuk:
mencari satu element pertama yang memenuhi kondisi tertentu.
Misalnya:
let numbers = [10, 20, 30, 40];
let result = numbers.find((number) => {
return number > 25;
});
Hasil:
30
Kenapa?
10 > 25 ❌
20 > 25 ❌
30 > 25 ✅
↓
berhenti
find() mengambil element pertama yang memenuhi kondisi.
11. find() pada project movie
Kode:
let selectedMovie = movies.find((movie) => {
return movie.id === movieId;
});
Misalnya:
movieId = 2;
Array:
movies = [
{ id: 1, name: "Interstellar" },
{ id: 2, name: "Fast and Furious" },
{ id: 3, name: "Inception" }
];
find() bekerja seperti ini:
Iterasi 1
movie = {
id: 1,
name: "Interstellar"
}
Cek:
movie.id === movieId
menjadi:
1 === 2
Hasil:
false
Lanjut.
Iterasi 2
movie = {
id: 2,
name: "Fast and Furious"
}
Cek:
2 === 2
Hasil:
true
Karena sudah true, find() mengembalikan object tersebut.
Hasil:
selectedMovie = {
id: 2,
name: "Fast and Furious"
}
12. Bedakan find() dan filter()
Ini sangat penting karena sebelumnya kita belajar filter().
find()
Mencari satu element:
let movie = movies.find((movie) => {
return movie.id === 2;
});
Hasil:
{
id: 2,
name: "Fast and Furious"
}
filter()
Mencari banyak element:
let movies = movies.filter((movie) => {
return movie.rating > 4;
});
Hasil:
[
{...},
{...},
{...}
]
Jadi:
| Method | Hasil |
|---|---|
find() | 1 element / undefined |
filter() | Array berisi 0 atau lebih element |
Mental model
find()
"Carikan AKU SATU movie yang cocok."
filter()
"Carikan SEMUA movie yang cocok."
Dalam kasus Details:
ID → satu movie
maka cocok menggunakan:
find()
13. Kenapa menggunakan ===?
Kode:
movie.id === movieId
Artinya ID harus sama nilai dan tipenya.
Misalnya:
2 === 2
→ true
Tetapi:
2 === "2"
→ false
Ini penting karena ID bisa saja berupa Number atau String.
Dalam project lecture, kemungkinan:
movie.id
adalah Number:
2
dan yang dikirim:
2
sehingga:
2 === 2
→ true.
14. Setelah menemukan movie, kita membuat HTML
Sekarang kita punya:
selectedMovie
Misalnya:
{
id: 2,
name: "Fast and Furious",
description: "Lorem ipsum...",
rating: 4.2,
genre: ["action"],
releaseYear: 2004,
image: "images/fast.jpg"
}
Kita ingin mengubah data tersebut menjadi HTML.
Caranya menggunakan template literal.
Contoh sederhana:
let movieDetailHTML = `
<h2>${selectedMovie.name}</h2>
<p>${selectedMovie.description}</p>
`;
Hasil akhirnya kira-kira:
<h2>Fast and Furious</h2>
<p>Lorem ipsum...</p>
15. Kenapa template literal sangat berguna di sini?
Bayangkan kita harus membuat HTML dengan String biasa:
let html = "<h2>" + selectedMovie.name + "</h2>";
Kalau HTML-nya panjang, menjadi susah dibaca.
Template literal:
let html = `
<h2>${selectedMovie.name}</h2>
<p>${selectedMovie.description}</p>
`;
jauh lebih nyaman.
Kita tinggal menulis HTML seperti biasa dan memasukkan data menggunakan:
${...}
16. Data movie dimasukkan ke HTML
Contohnya:
Image
<img src="${displayMovieBanner(selectedMovie.image)}">
Kita menggunakan function yang sudah dibuat sebelumnya:
displayMovieBanner()
Tujuannya kalau movie tidak mempunyai image:
image: ""
maka digunakan:
images/not-found.jpg
Jadi lecture sekarang menggunakan kembali function dari lecture sebelumnya.
17. Movie name
${formatMovieName(selectedMovie.name)}
Misalnya data:
name: "fast furious"
function:
formatMovieName()
mengubahnya menjadi:
Fast Furious
Jadi data asli tidak perlu diubah.
18. Description
${selectedMovie.description}
Berbeda dengan card sebelumnya.
Card menggunakan:
formatMovieDescription(movie.description)
karena card hanya membutuhkan preview.
Detail menggunakan:
selectedMovie.description
karena kita ingin menampilkan description lengkap.
Jadi:
Movie Card
↓
description pendek
Movie Detail
↓
description lengkap
19. Release year
${selectedMovie.releaseYear}
Misalnya:
releaseYear: 2004
menjadi:
2004
20. Rating angka + rating bintang
Lecture menampilkan rating seperti:
4.2 ★★★★★
Bagian angka:
${selectedMovie.rating}
Bagian bintang:
${displayStarRatings(selectedMovie.rating)}
Jadi:
${selectedMovie.rating}
${displayStarRatings(selectedMovie.rating)}
Misalnya:
selectedMovie.rating = 4.2
hasilnya:
4.2 ★★★★★
Function:
displayStarRatings()
adalah function yang kita buat di lecture sebelumnya.
Ini konsep penting dalam programming:
Jangan mengulang logic yang sudah dibuat. Gunakan kembali function yang sudah ada.
21. Genre
Genre menggunakan:
formatGenre(selectedMovie.genre)
Misalnya:
genre: ["action", "sci-fi", "drama"]
Function tersebut menghasilkan:
Action, Sci-fi, Drama
Jadi keseluruhan HTML detail kira-kira:
let movieDetailHTML = `
<img src="${displayMovieBanner(selectedMovie.image)}">
<h2>${formatMovieName(selectedMovie.name)}</h2>
<p>${selectedMovie.description}</p>
<div>
Release Year: ${selectedMovie.releaseYear}
</div>
<div>
Rating:
${selectedMovie.rating}
${displayStarRatings(selectedMovie.rating)}
</div>
<div>
Genre:
${formatGenre(selectedMovie.genre)}
</div>
`;
22. Sekarang HTML tersebut harus dimasukkan ke DOM
Membuat:
let movieDetailHTML = `...`;
belum membuatnya muncul di browser.
Kenapa?
Karena kita baru membuat String.
movieDetailHTML
↓
String
↓
belum ada di DOM
Kita harus memasukkannya ke container.
23. Ambil container
Misalnya HTML memiliki:
<div id="selected-movie-details"></div>
Kita ambil:
let container =
document.getElementById("selected-movie-details");
Sekarang:
container
↓
<div id="selected-movie-details"></div>
24. Kenapa innerHTML = "" dulu?
Lecture melakukan:
container.innerHTML = "";
Tujuannya membersihkan detail movie sebelumnya.
Bayangkan user pertama kali klik:
Interstellar
container berisi:
<div>
Interstellar
</div>
Kemudian user menutup modal dan klik:
Bahubali
Kalau kita tidak menghapus isi sebelumnya, kita berisiko menambahkan HTML baru ke HTML lama.
Jadi:
container.innerHTML = "";
artinya:
“Kosongkan container ini dulu.”
Kemudian:
container.insertAdjacentHTML(
"beforeend",
movieDetailHTML
);
memasukkan detail baru.
25. Apa arti "beforeend"?
Misalnya:
<div id="container">
</div>
Kode:
container.insertAdjacentHTML(
"beforeend",
movieDetailHTML
);
akan menghasilkan:
<div id="container">
...movieDetailHTML...
</div>
beforeend berarti:
di dalam element, tepat sebelum closing tag.
Visual:
<div id="container">
↑
│
│ movieDetailHTML
│
└────────────── </div>
26. Alur lengkap function showMovieDetails()
Sekarang kita bisa melihat function secara utuh secara konsep:
function showMovieDetails(movieId) {
// 1. Tampilkan modal
showMovieDetailsModal();
// 2. Cari movie
let selectedMovie = movies.find((movie) => {
return movie.id === movieId;
});
// 3. Buat HTML
let movieDetailHTML = `
...
`;
// 4. Ambil container
let container =
document.getElementById("selected-movie-details");
// 5. Bersihkan isi lama
container.innerHTML = "";
// 6. Masukkan HTML baru
container.insertAdjacentHTML(
"beforeend",
movieDetailHTML
);
}
Ini sebenarnya inti seluruh lecture.
27. Alur ketika user klik Details
Misalnya user klik Details pada Bahubali.
User klik Details
↓
onclick="showMovieDetails(5)"
↓
showMovieDetails(5)
↓
showMovieDetailsModal()
↓
modal ditampilkan
↓
movies.find(...)
↓
cari movie dengan id = 5
↓
selectedMovie = Bahubali
↓
buat movieDetailHTML
↓
ambil container
↓
container.innerHTML = ""
↓
insertAdjacentHTML()
↓
detail Bahubali masuk DOM
↓
Browser render
↓
User melihat detail
28. Ketika tombol X diklik
Sekarang user menekan tombol close:
<button onclick="hideMovieDetailsModal()">
X
</button>
Maka:
Click X
↓
hideMovieDetailsModal()
↓
classList.add("hidden")
↓
display:none
↓
modal menghilang
Perhatikan bahwa kita tidak menghapus modal dari DOM.
Kita hanya menyembunyikannya.
show
↓
remove("hidden")
hide
↓
add("hidden")
29. Kenapa detail container dibersihkan setiap kali?
Ini penting.
Misalnya:
Klik pertama
Details Interstellar
container:
Interstellar
Klik kedua
Details Bahubali
Kalau tidak:
container.innerHTML = "";
bisa terjadi:
Interstellar
Bahubali
Padahal kita hanya ingin:
Bahubali
Jadi:
container.innerHTML = "";
memastikan bahwa kita selalu memulai dari kondisi kosong.
30. Hubungan dengan lecture sebelumnya
Lecture ini sebenarnya menggabungkan banyak materi sebelumnya.
find()
Dari array:
movies.find(...)
digunakan untuk mencari movie berdasarkan ID.
Template literal
`
<h2>${selectedMovie.name}</h2>
`
digunakan untuk membuat HTML dinamis.
insertAdjacentHTML()
container.insertAdjacentHTML(
"beforeend",
movieDetailHTML
);
digunakan untuk memasukkan HTML ke DOM.
classList
classList.remove("hidden");
classList.add("hidden");
digunakan untuk show/hide modal.
formatMovieName()
Untuk formatting nama.
formatGenre()
Untuk formatting genre.
displayStarRatings()
Untuk membuat rating menjadi bintang.
displayMovieBanner()
Untuk fallback image.
Jadi project ini mulai memperlihatkan kenapa kita belajar method-method tersebut satu per satu.
31. Yang sangat penting: data vs UI
Perhatikan bahwa kita tidak mengubah data movie.
Misalnya:
selectedMovie.name
tetap:
fast furious
Kita hanya membuat tampilan:
formatMovieName(selectedMovie.name)
menjadi:
Fast Furious
Begitu juga:
selectedMovie.genre
tetap:
["action", "sci-fi"]
tetapi ditampilkan sebagai:
Action, Sci-fi
Jadi:
DATA
↓
movies array
↓
JavaScript mengolah
↓
UI
Data asli tetap menjadi source of truth.
32. Kenapa find() sangat cocok untuk Details?
Bayangkan kita memiliki 1000 film.
User klik:
Details movie ID 785
Kita tidak ingin:
“Tampilkan semua movie.”
Kita ingin:
“Cari movie dengan ID 785.”
Maka:
movies.find((movie) => movie.id === 785);
sangat masuk akal.
Berbeda dengan filter:
movies.filter((movie) => movie.id === 785);
Ini juga bisa secara hasil mendapatkan satu movie, tetapi hasilnya berupa Array:
[
{
id: 785,
...
}
]
Sedangkan find() langsung:
{
id: 785,
...
}
Lebih cocok karena kita memang membutuhkan satu object movie.
33. find() vs filter() vs map() vs forEach()
Sekarang karena project sudah menggunakan banyak method, bagus kalau kita satukan.
| Method | Tujuan | Return |
|---|---|---|
forEach() | melakukan sesuatu untuk setiap element | biasanya undefined |
map() | mengubah setiap element | Array baru |
filter() | mengambil element yang memenuhi kondisi | Array baru |
find() | mencari element pertama yang memenuhi kondisi | 1 element / undefined |
Contoh:
movies.forEach(...)
“Lakukan sesuatu untuk semua movie.”
movies.map(...)
“Ubah semua movie menjadi bentuk lain.”
movies.filter(...)
“Ambil semua movie yang memenuhi syarat.”
movies.find(...)
“Cari satu movie pertama yang memenuhi syarat.”
34. Satu hal teknis yang perlu diperhatikan: find() bisa menghasilkan undefined
Misalnya:
let selectedMovie = movies.find((movie) => {
return movie.id === 999;
});
Kalau tidak ada movie dengan ID 999:
selectedMovie
akan menjadi:
undefined
Kalau kemudian kita melakukan:
selectedMovie.name
akan error.
Karena kita sedang melakukan:
undefined.name
Dalam project sederhana ini ID seharusnya valid karena berasal dari movie yang memang ada.
Tetapi dalam aplikasi nyata, biasanya kita tetap melakukan pengecekan:
if (!selectedMovie) {
return;
}
35. Satu detail penting tentang onclick
Lecture menggunakan:
onclick="showMovieDetails(${movie.id})"
Perhatikan bahwa kita menggunakan:
${movie.id}
bukan:
${movie}
Karena:
movie
adalah object.
Sedangkan:
movie.id
adalah nilai sederhana, misalnya:
5
Sehingga hasil HTML menjadi:
onclick="showMovieDetails(5)"
Ini mudah dipahami oleh inline handler.
36. Jangan bingung antara dua movie
Ada dua konsep yang namanya sama.
movie di find()
movies.find((movie) => {
return movie.id === movieId;
});
movie di sini adalah parameter callback.
Artinya:
movie = movie yang sedang diperiksa
selectedMovie
let selectedMovie = movies.find(...);
Ini adalah movie yang akhirnya ditemukan.
Jadi:
movies.find()
↓
movie (satu per satu)
↓
yang cocok
↓
selectedMovie
37. Gambaran visual seluruh fitur
Ini mental model yang paling bagus untuk diingat:
MOVIES ARRAY
│
│
renderAllMovies()
│
↓
┌──────────────┐
│ Movie Card │
│ │
│ Interstellar │
│ [ Details ] │
└──────┬───────┘
│
CLICK
│
↓
showMovieDetails(id)
│
↓
movies.find()
│
↓
selectedMovie
│
↓
create HTML string
│
↓
formatMovieName()
formatGenre()
displayStarRatings()
displayMovieBanner()
│
↓
movieDetailHTML
│
↓
innerHTML = ""
│
↓
insertAdjacentHTML()
│
↓
DOM
│
↓
SHOW MODAL
38. Bedakan showMovieDetailsModal() dan showMovieDetails()
Nama function-nya memang mirip, tetapi tugasnya berbeda.
showMovieDetailsModal()
Tugasnya hanya:
Tampilkan modal.
function showMovieDetailsModal() {
modal.classList.remove("hidden");
}
showMovieDetails(movieId)
Tugasnya jauh lebih besar:
Cari movie dan isi modal dengan detail movie tersebut.
function showMovieDetails(movieId) {
showMovieDetailsModal();
let selectedMovie = movies.find(...);
// buat HTML
// masukkan HTML
}
Jadi:
showMovieDetails()
│
├── showMovieDetailsModal()
│
├── find movie
│
├── create HTML
│
└── render HTML
39. Pola penting: Data → Transform → Render
Project ini mulai menggunakan pola yang sangat sering muncul dalam JavaScript.
DATA
↓
movies
↓
TRANSFORM
↓
find()
formatMovieName()
formatGenre()
displayStarRatings()
displayMovieBanner()
↓
HTML
↓
DOM
↓
UI
Contohnya:
selectedMovie.name
↓
formatMovieName(selectedMovie.name)
↓
Fast And Furious
↓
<h2>Fast And Furious</h2>
↓
DOM
↓
browser menampilkan.
40. Hubungan dengan lecture sorting dan filtering
Sebelumnya:
Sorting
movies.sort(...)
mengubah urutan data.
Search
movies.filter(...)
menghasilkan movie yang namanya cocok.
Genre filter
movies.filter(...)
menghasilkan movie yang genre-nya cocok.
Sekarang Details
movies.find(...)
mengambil satu movie tertentu.
Jadi sekarang kita sudah memiliki:
movies
│
├── sort() → mengurutkan
│
├── filter() → menyaring banyak movie
│
└── find() → mencari satu movie
Ini salah satu bagian terpenting dari project ini.
41. Cheat sheet lecture ini
Tampilkan modal
modal.classList.remove("hidden");
Sembunyikan modal
modal.classList.add("hidden");
Cari satu movie
let selectedMovie = movies.find((movie) => {
return movie.id === movieId;
});
Buat HTML
let html = `
<h2>${selectedMovie.name}</h2>
`;
Kosongkan container
container.innerHTML = "";
Masukkan HTML
container.insertAdjacentHTML(
"beforeend",
html
);
Tombol Details
onclick="showMovieDetails(2)"
42. Kesimpulan paling sederhana
Kalau kamu hanya ingin mengingat 5 hal dari lecture ini, ingat ini:
1. Tombol Details mengirim ID
showMovieDetails(movie.id)
2. ID digunakan untuk mencari movie
movies.find((movie) => movie.id === movieId)
3. Movie yang ditemukan disimpan
let selectedMovie = ...
4. Data movie dimasukkan ke template literal
let html = `
<h2>${selectedMovie.name}</h2>
`;
5. HTML dimasukkan ke DOM
container.innerHTML = "";
container.insertAdjacentHTML(
"beforeend",
html
);
Jadi rumus mentalnya:
CLICK DETAILS
↓
movie.id
↓
find()
↓
selectedMovie
↓
template literal
↓
HTML string
↓
insertAdjacentHTML()
↓
MODAL DETAIL
Intinya: lecture ini mengajarkan bagaimana mengambil satu object dari array berdasarkan ID, lalu menggunakan object tersebut untuk membuat UI yang dinamis. Ini adalah langkah penting dari JavaScript dasar menuju pola aplikasi web yang benar-benar interaktif.