Masukkan Password
74 Cineflix: Urutkan Daftar Film
Lecture ini penting karena mulai menggabungkan beberapa konsep yang sudah kamu pelajari sebelumnya: array, object, forEach(), function, callback, sort(), operator -, if, !, dan rendering DOM.
Fokus utamanya adalah:
Bagaimana mengurutkan array
moviesberdasarkan rating atau tahun rilis, lalu menampilkan hasil pengurutan tersebut ke UI.
1. Gambaran besar fitur yang dibuat
Di project kita ada dua tombol:
Sort by:
[ Ratings ] [ Release Year ]
Kita ingin:
Ketika klik Ratings
Pertama kali:
rating kecil β rating besar
2.5
3.0
3.8
4.2
4.7
Klik lagi:
rating besar β rating kecil
4.7
4.2
3.8
3.0
2.5
Klik lagi:
rating kecil β rating besar
Jadi tombolnya bergantian:
ASC β DESC β ASC β DESC β ...
Hal yang sama dilakukan untuk releaseYear.
2. Data movies yang akan diurutkan
Misalnya kita punya:
let movies = [
{
name: "Movie A",
rating: 4.5,
releaseYear: 2010
},
{
name: "Movie B",
rating: 2.8,
releaseYear: 2004
},
{
name: "Movie C",
rating: 4.9,
releaseYear: 2015
}
];
Awalnya:
Movie A β rating 4.5 β 2010
Movie B β rating 2.8 β 2004
Movie C β rating 4.9 β 2015
Kalau sort berdasarkan rating ascending:
Movie B β 2.8
Movie A β 4.5
Movie C β 4.9
Kalau descending:
Movie C β 4.9
Movie A β 4.5
Movie B β 2.8
3. sort() adalah inti dari lecture ini
JavaScript mempunyai method:
array.sort()
Untuk sorting yang lebih spesifik, kita memberikan callback function.
Contoh:
movies.sort((current, next) => {
return current.rating - next.rating;
});
Ini adalah pola yang sangat penting untuk kamu hafalkan:
array.sort((a, b) => {
return a.property - b.property;
});
Untuk angka:
hasil negatif β a tetap sebelum b
hasil positif β b dipindah sebelum a
hasil 0 β relatif tidak perlu ditukar
4. Apa maksud current dan next?
Pada:
movies.sort((current, next) => {
return current.rating - next.rating;
});
current dan next adalah dua elemen yang sedang dibandingkan.
Misalnya:
current = Movie A
rating = 4.5
next = Movie B
rating = 2.8
Maka:
current.rating - next.rating
menjadi:
4.5 - 2.8
hasil:
1.7
Hasilnya positif.
Artinya urutan kedua elemen tersebut perlu disesuaikan agar nilai yang lebih kecil berada di depan.
Hasil akhirnya:
Movie B β 2.8
Movie A β 4.5
5. Kenapa current.rating - next.rating menghasilkan ascending?
Ini bagian paling penting dari lecture.
Misalnya:
current.rating = 2.8;
next.rating = 4.5;
Maka:
2.8 - 4.5
hasil:
-1.7
Negatif.
Artinya:
2.8 tetap di depan 4.5
Dan memang kita mau:
2.8
4.5
Sekarang dibalik:
current = 4.5
next = 2.8
Maka:
4.5 - 2.8
hasil:
+1.7
Positif.
Artinya:
4.5 harus berada setelah 2.8
Jadi:
2.8
4.5
Kesimpulannya:
current.rating - next.rating
menghasilkan:
ASCENDING
kecil β besar
6. Cara mudah mengingat sort()
Untuk angka:
Ascending
a - b
Artinya:
kecil β besar
Descending
b - a
Artinya:
besar β kecil
Jadi hafalkan:
ASC β a - b
DESC β b - a
Contohnya:
// ascending
movies.sort((a, b) => a.rating - b.rating);
// descending
movies.sort((a, b) => b.rating - a.rating);
Ini salah satu pola yang sangat sering dipakai dalam JavaScript.
7. Membuat event listener untuk tombol Rating
HTML misalnya:
<button id="sort-movie-by-rating">
Ratings
</button>
Kemudian JavaScript:
let sortMovieByRatingButton =
document.getElementById("sort-movie-by-rating");
sortMovieByRatingButton.addEventListener("click", sortMoviesByRating);
Artinya:
User klik tombol
β
event "click"
β
sortMoviesByRating()
β
movies di-sort
β
UI di-render ulang
Perhatikan:
sortMoviesByRating
bukan:
sortMoviesByRating()
Karena kita memberikan function-nya sebagai callback.
8. Function sortMoviesByRating()
Versi paling sederhana:
function sortMoviesByRating() {
movies.sort((current, next) => {
return current.rating - next.rating;
});
renderAllMovies(movies);
}
Ada dua pekerjaan:
Pertama
movies.sort(...)
Mengubah urutan array.
Kedua
renderAllMovies(movies);
Menampilkan array yang sudah berubah ke UI.
Jadi:
movies
β
sort()
β
movies sudah terurut
β
renderAllMovies()
β
UI diperbarui
9. Ini membawa kita ke konsep penting: sort() memodifikasi array asli
Ini sangat penting.
Misalnya:
let numbers = [5, 2, 8, 1];
numbers.sort((a, b) => a - b);
Setelah sort():
console.log(numbers);
hasil:
[1, 2, 5, 8]
Jadi sort() bukan sekadar menghasilkan tampilan baru.
Ia mengubah urutan array yang asli.
Dalam project kita:
movies.sort(...)
mengubah langsung:
movies
Itulah kenapa setelah sorting kita cukup melakukan:
renderAllMovies(movies);
karena movies sekarang sudah berisi urutan baru.
10. Kenapa awalnya UI tidak berubah?
Ini bagian lecture yang bagus untuk memahami perbedaan antara data dan UI.
Misalnya:
movies.sort((a, b) => a.rating - b.rating);
Data berubah:
movies array
sebelum:
A
B
C
sesudah:
B
A
C
Tetapi HTML yang sudah ada di browser:
UI
A
B
C
tidak otomatis berubah.
Kenapa?
Karena JavaScript mengubah array, bukan HTML.
11. Data dan UI adalah dua hal berbeda
Bayangkan:
DATA
movies array
β
rendering
β
UI
Kalau kita mengubah data:
movies.sort(...)
yang berubah adalah:
DATA
Bukan:
UI
Maka kita perlu:
renderAllMovies(movies);
Supaya:
DATA berubah
β
render ulang
β
UI berubah
Ini konsep yang sangat penting untuk project-project JavaScript berikutnya.
12. Masalah berikutnya: kenapa malah movie muncul dua kali?
Lecture kemudian menemukan masalah baru.
Misalnya awalnya UI:
Movie A
Movie B
Movie C
Kemudian kita klik sort.
renderAllMovies(movies) dipanggil lagi.
Kalau function tersebut hanya melakukan:
movieList.forEach(...)
maka HTML baru hanya ditambahkan ke HTML lama.
Hasilnya bisa menjadi:
Movie A
Movie B
Movie C
Movie B
Movie A
Movie C
Jadi bukan mengganti UI lama.
Melainkan:
menambahkan UI baru di bawah UI lama.
13. Solusinya: kosongkan container terlebih dahulu
Di awal renderAllMovies():
function renderAllMovies(movieList) {
movieListSection.innerHTML = "";
movieList.forEach((movie) => {
// render movie
});
}
Perhatikan:
movieListSection.innerHTML = "";
Artinya:
“Hapus semua isi movie list container.”
Baru setelah itu:
movieList.forEach(...)
membuat card baru.
Flow-nya:
renderAllMovies(movies)
β
hapus UI lama
β
innerHTML = ""
β
loop movies
β
buat card baru
β
insertAdjacentHTML()
β
UI baru
14. Kenapa ini penting saat sorting?
Sekarang ketika klik Ratings:
movies array
β
sort()
β
urutan berubah
β
renderAllMovies(movies)
β
hapus card lama
β
buat card berdasarkan urutan baru
β
UI baru
Misalnya:
Sebelum
Movie A β 4.5
Movie B β 2.8
Movie C β 4.9
Klik Ratings:
sort()
menjadi:
Movie B β 2.8
Movie A β 4.5
Movie C β 4.9
Kemudian render ulang:
Movie B
Movie A
Movie C
15. Sekarang masuk ke fitur ASC β DESC
Lecture kemudian membuat:
let sortAscending = true;
Ini disebut flag variable.
Flag adalah variable yang biasanya menyimpan:
true
atau:
false
untuk menandai suatu kondisi.
Di sini:
sortAscending
berarti:
“Apakah sorting berikutnya harus ascending?”
Awalnya:
sortAscending = true;
Jadi klik pertama:
ASC
16. Struktur if-nya
Kira-kira:
function sortMoviesByRating() {
if (sortAscending) {
movies.sort((current, next) => {
return current.rating - next.rating;
});
} else {
movies.sort((current, next) => {
return next.rating - current.rating;
});
}
sortAscending = !sortAscending;
renderAllMovies(movies);
}
Mari kita pecah.
17. Kalau sortAscending === true
Masuk ke:
if (sortAscending) {
Kemudian:
movies.sort((current, next) => {
return current.rating - next.rating;
});
Artinya:
ASCENDING
2.5
3.0
4.2
4.8
Setelah selesai:
sortAscending = !sortAscending;
Karena awalnya:
sortAscending = true;
maka:
!true
menjadi:
false
Sekarang:
sortAscending = false;
18. Klik kedua
Saat tombol diklik lagi:
sortAscending
sekarang:
false
Maka:
if (sortAscending) {
tidak dijalankan.
Masuk ke else:
else {
movies.sort((current, next) => {
return next.rating - current.rating;
});
}
Perhatikan urutannya berubah:
current.rating - next.rating
menjadi:
next.rating - current.rating
Hasilnya:
DESCENDING
4.8
4.2
3.0
2.5
Kemudian:
sortAscending = !sortAscending;
Sekarang:
false β true
19. Klik ketiga
Karena sekarang:
sortAscending === true
maka:
current.rating - next.rating
digunakan lagi.
Hasil:
ASCENDING
2.5
3.0
4.2
4.8
Jadi kita mendapatkan:
Klik 1
true
β
ASC
β
false
Klik 2
false
β
DESC
β
true
Klik 3
true
β
ASC
β
false
Klik 4
false
β
DESC
20. Kenapa !sortAscending bisa membalik nilainya?
Operator:
!
adalah logical NOT.
Kita sudah belajar ini sebelumnya:
!true // false
!false // true
Jadi:
sortAscending = !sortAscending;
berarti:
“Ambil nilai sekarang, lalu balikkan.”
Visual:
true
β !
false
β !
true
β !
false
Ini teknik yang sangat umum untuk toggle.
Contoh lain:
let isDarkMode = false;
isDarkMode = !isDarkMode;
menjadi:
false β true
Kalau dipanggil lagi:
true β false
21. Implementasi lengkap sorting rating
Kurang lebih seperti ini:
let sortAscending = true;
function sortMoviesByRating() {
if (sortAscending) {
movies.sort((current, next) => {
return current.rating - next.rating;
});
} else {
movies.sort((current, next) => {
return next.rating - current.rating;
});
}
sortAscending = !sortAscending;
renderAllMovies(movies);
}
Perhatikan urutannya:
1. Cek mode sorting
β
2. Sort array
β
3. Balik flag
β
4. Render ulang UI
22. Sekarang sorting berdasarkan release year
Prinsipnya persis sama.
Bedanya hanya property yang digunakan.
Rating:
current.rating - next.rating
Release year:
current.releaseYear - next.releaseYear
23. Ascending release year
Misalnya:
Movie A β 2010
Movie B β 2004
Movie C β 2015
Kita ingin:
2004
2010
2015
Maka:
movies.sort((current, next) => {
return current.releaseYear - next.releaseYear;
});
Karena:
2004 - 2010 = -6
negatif β 2004 tetap lebih dulu.
24. Descending release year
Kalau ingin:
2015
2010
2004
gunakan:
movies.sort((current, next) => {
return next.releaseYear - current.releaseYear;
});
Jadi pola yang sama:
ASC:
current.property - next.property
DESC:
next.property - current.property
25. Full function release year
Misalnya:
function sortMoviesByReleaseYear() {
if (sortAscending) {
movies.sort((current, next) => {
return current.releaseYear - next.releaseYear;
});
} else {
movies.sort((current, next) => {
return next.releaseYear - current.releaseYear;
});
}
sortAscending = !sortAscending;
renderAllMovies(movies);
}
Kemudian event listener:
let sortMovieByReleaseYearButton =
document.getElementById("sort-movie-by-release-year");
sortMovieByReleaseYearButton.addEventListener(
"click",
sortMoviesByReleaseYear
);
26. Tapi ada satu hal yang perlu kamu perhatikan
Kalau kita menggunakan satu variable:
let sortAscending = true;
untuk dua tombol:
Ratings
Release Year
maka state sorting keduanya saling berbagi.
Contohnya:
Awal:
sortAscending = true
Klik Ratings
β ASC
β sortAscending = false
Klik Release Year
β karena false
β DESC
Padahal mungkin kita ingin setiap tombol punya status sendiri.
Untuk project sederhana lecture, satu flag mungkin cukup untuk memperkenalkan konsep.
Tetapi dalam aplikasi yang lebih rapi, biasanya kita pisahkan:
let ratingSortAscending = true;
let releaseYearSortAscending = true;
Sehingga:
Ratings
ASC β DESC
punya state sendiri, dan:
Release Year
ASC β DESC
punya state sendiri.
Catatan ini bukan inti lecture, tapi bagus untuk memahami bahwa flag menyimpan “state” dari fitur tertentu.
27. sort() + object: ini yang sebenarnya sedang kita lakukan
Ini mungkin terlihat seperti:
movies.sort(...)
sederhana.
Tapi sebenarnya kita sedang melakukan:
Array
β
berisi Object
β
setiap Object punya property
β
bandingkan property tertentu
Misalnya:
movies = [
{ name: "A", rating: 4.5 },
{ name: "B", rating: 2.8 },
{ name: "C", rating: 4.9 }
];
Kita tidak membandingkan object secara langsung.
Kita membandingkan:
current.rating
dengan:
next.rating
Jadi:
Movie object
β
ambil property rating
β
bandingkan angka
β
tentukan urutan object
28. sort() tidak hanya untuk angka
Ini juga penting untuk pemahaman ke depan.
Untuk angka:
numbers.sort((a, b) => a - b);
Untuk object berdasarkan rating:
movies.sort((a, b) => a.rating - b.rating);
Untuk object berdasarkan year:
movies.sort((a, b) => a.releaseYear - b.releaseYear);
Jadi pola dasarnya:
array.sort((a, b) => a.property - b.property);
29. Kenapa tidak cukup movies.sort()?
Ini jebakan umum.
Kalau:
let numbers = [10, 2, 5, 1];
numbers.sort();
hasilnya bisa:
[1, 10, 2, 5]
Kenapa?
Karena default sort() membandingkan elemen sebagai String, bukan melakukan numeric sorting seperti yang kita inginkan.
Sehingga:
"10"
"2"
"5"
"1"
diurutkan secara lexicographical.
Untuk angka, lebih aman memberikan compare function:
numbers.sort((a, b) => a - b);
hasil:
1
2
5
10
30. Hubungan dengan callback yang sudah kamu pelajari
Sebelumnya kamu sudah belajar:
addEventListener("click", function () {
...
});
Function yang diberikan ke addEventListener() adalah callback.
Di sort() juga sama:
movies.sort(function (current, next) {
return current.rating - next.rating;
});
Function ini diberikan kepada sort() untuk digunakan oleh JavaScript saat melakukan perbandingan.
Jadi:
addEventListener()
β
menerima callback
β
callback dipanggil ketika event terjadi
Sedangkan:
sort()
β
menerima callback
β
callback dipanggil ketika elemen perlu dibandingkan
Ini memperkuat konsep callback yang sudah kamu pelajari.
31. Hubungan dengan forEach() dan map()
Sekarang project kita sudah menggunakan beberapa array method:
| Method | Tujuan di project |
|---|---|
forEach() | melakukan rendering untuk setiap movie |
map() | mengubah setiap genre menjadi format baru |
flatMap() | latihan transformasi + flatten |
sort() | mengurutkan movie |
push() | menambahkan movie |
filter() | nanti untuk filtering/search |
find() | kemungkinan untuk mencari movie tertentu |
Jadi jangan menganggap semua array method melakukan hal yang sama.
Mental modelnya:
forEach β lakukan sesuatu
map β ubah setiap item
filter β pilih beberapa item
find β cari satu item
sort β urutkan item
32. Hubungan sort() dengan rendering project
Sekarang arsitektur project kita semakin jelas:
movies
β
βββββββββ΄βββββββββ
β β
sort filter
β β
βββββββββ¬βββββββββ
β
renderAllMovies()
β
movieListSection
β
UI
Data movies adalah source of truth.
Misalnya:
movies
β
[Movie B, Movie A, Movie C]
Kemudian renderer membaca array tersebut.
Jadi UI mengikuti isi array.
33. Kenapa renderAllMovies() harus clear dulu?
Karena kita menggunakan:
insertAdjacentHTML("beforeend", movieCard);
beforeend berarti:
tambahkan HTML baru di akhir isi element.
Jadi:
movieListSection.insertAdjacentHTML(
"beforeend",
movieCard
);
tidak menghapus movie lama.
Maka sebelum rendering ulang:
movieListSection.innerHTML = "";
Kemudian:
insertAdjacentHTML(...)
untuk membuat UI baru.
Pola ini:
CLEAR
β
RENDER
sangat umum pada project sederhana seperti ini.
34. Full flow ketika user klik Ratings
Mari kita ikuti benar-benar dari awal sampai akhir.
User melihat:
Movie A βββββ
Movie B βββββ
Movie C βββββ
User klik:
[ Ratings ]
Step 1 β event terjadi
click
Step 2 β event listener menjalankan:
sortMoviesByRating
Step 3 β cek flag
sortAscending
misalnya:
true
Step 4 β sorting ascending
movies.sort((a, b) => a.rating - b.rating);
Step 5 β array berubah
Movie B β 2.8
Movie A β 4.5
Movie C β 4.9
Step 6 β toggle flag
sortAscending = !sortAscending;
true β false
Step 7 β render ulang
renderAllMovies(movies);
Step 8 β clear UI lama
movieListSection.innerHTML = "";
Step 9 β render movie berdasarkan array baru
Movie B
Movie A
Movie C
Hasil akhirnya:
βββββ Movie B
βββββ Movie A
βββββ Movie C
35. Flow diagram lengkap
User klik "Ratings"
β
click event
β
sortMoviesByRating()
β
cek sortAscending
β
ββββββ΄βββββ
β β
true false
β β
β β
ASC DESC
a.rating b.rating
- -
b.rating a.rating
β β
ββββββ¬βββββ
β
movies berubah
β
sortAscending = !sortAscending
β
renderAllMovies(movies)
β
movieListSection.innerHTML = ""
β
forEach()
β
buat movie card
β
insertAdjacentHTML()
β
UI
36. Bagian yang sering membingungkan: sort() tidak “menggambar” UI
Ini harus benar-benar dipisahkan di kepala:
sort()
Tugasnya:
mengubah URUTAN DATA
Bukan:
mengubah HTML
renderAllMovies()
Tugasnya:
mengubah DATA menjadi UI
Jadi:
sort()
β
DATA berubah
renderAllMovies()
β
UI berubah
Dua fungsi ini punya tanggung jawab berbeda.
37. Analogi sederhana
Bayangkan kamu punya daftar buku di Excel.
Awalnya:
Buku A β rating 4.5
Buku B β rating 2.8
Buku C β rating 4.9
Kamu klik tombol “Sort”.
Excel mengubah urutan datanya:
Buku B
Buku A
Buku C
Tetapi dalam website, HTML yang sudah digambar di layar tidak otomatis tahu bahwa array JavaScript berubah.
Jadi JavaScript harus berkata:
“Oke, datanya sudah berubah. Sekarang gambar ulang daftar di layar.”
Itulah:
renderAllMovies(movies);
38. Ringkasan syntax yang wajib kamu pahami
Ascending angka
array.sort((a, b) => a - b);
Descending angka
array.sort((a, b) => b - a);
Object berdasarkan property
movies.sort((a, b) => a.rating - b.rating);
Object berdasarkan property descending
movies.sort((a, b) => b.rating - a.rating);
Toggle Boolean
sortAscending = !sortAscending;
Render ulang
renderAllMovies(movies);
Clear container
movieListSection.innerHTML = "";
39. Cheat sheet sort() yang perlu kamu hafalkan
SORT ANGKA
ASCENDING DESCENDING
kecil β besar besar β kecil
a - b b - a
β β
1, 2, 3 3, 2, 1
Untuk object:
rating:
a.rating - b.rating
β
ASCENDING
b.rating - a.rating
β
DESCENDING
Untuk year:
a.releaseYear - b.releaseYear
β
ASCENDING
b.releaseYear - a.releaseYear
β
DESCENDING
40. Hal terpenting dari lecture ini
Kalau saya sederhanakan lecture panjang ini menjadi 6 konsep, yaitu:
1. sort() digunakan untuk mengurutkan Array
movies.sort(...)
2. Callback sort() membandingkan dua element
(a, b) => ...
3. Untuk angka
a - b
= ascending
b - a
= descending
4. sort() mengubah array asli
movies.sort(...)
membuat urutan movies berubah.
5. Perubahan data tidak otomatis mengubah UI
Maka perlu:
renderAllMovies(movies);
6. Sebelum render ulang, hapus UI lama
movieListSection.innerHTML = "";
π§ Mental model terakhir
Pegang pola ini:
MOVIES ARRAY
β
β
user klik SORT
β
β
sort()
β
βββββββββ΄ββββββββ
β β
ASC DESC
a - b b - a
β β
βββββββββ¬ββββββββ
β
array berubah
β
β
renderAllMovies()
β
β
hapus UI sebelumnya
β
β
forEach()
β
β
buat movie cards
β
β
UI
Dan satu kalimat yang menurut saya paling penting untuk kamu ingat dari lecture ini:
sort()mengubah urutan data, sedangkanrenderAllMovies()mengubah hasil data tersebut menjadi tampilan di browser.
Jadi ketika kamu melihat fitur seperti sort, filter, search, delete, create di project ini, selalu pikirkan dua lapisan:
DATA (`movies`)
β
LOGIC (sort/filter/search)
β
RENDER
β
UI
Itu akan sangat membantu ketika project ini mulai menjadi lebih kompleks.