Masukkan Password
79 Cineflix: Membuat Film
Lecture ini adalah bagian terakhir dari project CIN/Cinix, yaitu menambahkan fitur Create Movie: user mengisi form → JavaScript membaca data form → membuat object movie baru → memasukkannya ke array movies → menutup form → me-render ulang daftar movie.
Ini sebenarnya lecture yang sangat bagus karena menggabungkan banyak konsep yang sudah kamu pelajari sebelumnya: DOM, event, function, object, array, push(), forEach(), .value, .checked, getElementsByName(), preventDefault(), dan konsep data sebagai source of truth.
1. Gambaran besar fitur yang akan dibuat
Sebelumnya project kita punya:
let movies = [
{
id: 1,
name: "Interstellar",
rating: 4.8,
genre: ["sci-fi", "drama"]
},
{
id: 2,
name: "Bad Boys",
rating: 4.2,
genre: ["action", "comedy"]
}
];
Sekarang kita ingin user bisa mengisi form:
┌──────────────────────────────┐
│ Create Movie │
│ │
│ Movie Name: [__________] │
│ Description: [__________] │
│ Rating: [____] │
│ Release Year: [____] │
│ Genre: │
│ ☑ Action │
│ ☑ Drama │
│ ☐ Comedy │
│ │
│ [Create Movie] │
│ [Close] │
└──────────────────────────────┘
Misalnya user mengisi:
Name = Mission Impossible
Description = Some test description
Rating = 4
Release Year = 2012
Genre = action, drama
JavaScript harus mengubahnya menjadi object:
{
name: "Mission Impossible",
description: "Some test description",
rating: 4,
releaseYear: 2012,
genre: ["action", "drama"]
}
Kemudian:
movies.push(newMovie);
Sehingga:
movies sebelum:
[
movie1,
movie2
]
↓ push()
movies sesudah:
[
movie1,
movie2,
newMovie
]
Kemudian UI di-render ulang.
2. Arsitektur lengkapnya
Mental model paling penting dari lecture ini:
USER
│
│ klik "Create Movie"
↓
FORM MUNCUL
│
│ user mengisi data
↓
klik "Create Movie"
│
↓
submit event
│
↓
preventDefault()
│
↓
baca semua data form
│
↓
buat newMovie object
│
↓
movies.push(newMovie)
│
↓
hide form
│
↓
renderAllMovies(movies)
│
↓
MOVIE BARU MUNCUL
Jadi ada dua tahap klik:
Klik pertama
Tombol Create Movie di header:
Create Movie
↓
form muncul
Klik kedua
Tombol Create Movie di dalam form:
form submit
↓
baca data
↓
buat object
↓
push ke movies
↓
render ulang
Ini penting karena dua tombol tersebut punya fungsi yang berbeda.
3. Menampilkan form Create Movie
Di HTML, form awalnya memiliki class:
<section class="create-movie-section hidden">
CSS:
.hidden {
display: none;
}
Artinya:
create-movie-section
+
hidden
↓
tidak terlihat
Ketika class hidden dihapus:
createMovieSection.classList.remove("hidden");
maka:
create-movie-section
↓
hidden dihapus
↓
display: none hilang
↓
form terlihat
4. Function showCreateMovieModal()
Lecture membuat function:
function showCreateMovieModal() {
let createMovieSection =
document.querySelector(".create-movie-section");
createMovieSection.classList.remove("hidden");
}
Mari kita pecah.
Bagian pertama
document.querySelector(".create-movie-section");
Mencari element:
<section class="create-movie-section">
Hasilnya adalah DOM element object.
Kemudian disimpan:
let createMovieSection = ...
Bagian kedua
createMovieSection.classList.remove("hidden");
Artinya:
Hapus class
hiddendari element tersebut.
Misalnya awal:
<section class="create-movie-section hidden">
setelah:
classList.remove("hidden");
menjadi:
<section class="create-movie-section">
Karena .hidden sudah hilang, form terlihat.
5. Menutup form
Kebalikannya adalah:
function hideCreateMovieModal() {
let createMovieSection =
document.querySelector(".create-movie-section");
createMovieSection.classList.add("hidden");
}
Sekarang:
classList.add("hidden");
menambahkan kembali class hidden.
Jadi:
showCreateMovieModal()
↓
remove("hidden")
↓
FORM MUNCUL
hideCreateMovieModal()
↓
add("hidden")
↓
FORM HILANG
Ini sebenarnya konsep yang sudah kamu pelajari saat membuat modal sebelumnya.
6. Kenapa tombol header menggunakan showCreateMovieModal()?
Misalnya HTML:
<button onclick="showCreateMovieModal()">
Create Movie
</button>
Ketika user klik:
CLICK
↓
showCreateMovieModal()
↓
remove("hidden")
↓
form muncul
Sederhana.
7. Tombol Close
Di dalam form ada tombol Close:
<button onclick="hideCreateMovieModal()">
Close
</button>
Ketika diklik:
CLICK
↓
hideCreateMovieModal()
↓
add("hidden")
↓
form menghilang
8. Sekarang bagian paling penting: membaca data form
Setelah form muncul, user memasukkan:
Name
Description
Rating
Release Year
Genre
Masalahnya:
Bagaimana JavaScript mengambil data yang diketik user?
Untuk input biasa kita menggunakan:
element.value
Contoh:
<input id="name">
JavaScript:
document.getElementById("name").value
Misalnya user mengetik:
Mission Impossible
maka:
document.getElementById("name").value
menghasilkan:
"Mission Impossible"
9. Function readInputFieldValue()
Lecture membuat helper:
function readInputFieldValue(id) {
return document.getElementById(id).value;
}
Function ini sangat berguna karena kita tidak perlu menulis berulang-ulang:
document.getElementById("name").value
document.getElementById("description").value
document.getElementById("rating").value
document.getElementById("release-year").value
Kita cukup:
readInputFieldValue("name");
readInputFieldValue("description");
readInputFieldValue("rating");
readInputFieldValue("release-year");
10. Bagaimana function tersebut bekerja?
Misalnya:
readInputFieldValue("name");
Parameter:
id = "name"
Kemudian:
document.getElementById(id)
menjadi:
document.getElementById("name")
Lalu:
.value
mengambil isi input.
Jadi:
readInputFieldValue("name")
↓
document.getElementById("name")
↓
element input
↓
.value
↓
"Mission Impossible"
11. Kenapa rating perlu +?
Ini bagian yang sangat penting.
Misalnya HTML:
<input id="rating" type="number">
User memasukkan:
4.2
Kamu mungkin berpikir:
document.getElementById("rating").value
menghasilkan:
4.2
sebagai Number.
Tidak selalu.
Untuk form input, .value pada dasarnya menghasilkan String.
Jadi:
document.getElementById("rating").value
bisa menghasilkan:
"4.2"
bukan:
4.2
Perhatikan tanda kutip.
12. Kenapa String harus diubah menjadi Number?
Karena property:
rating
kita inginkan sebagai Number.
Bukan:
{
rating: "4.2"
}
tetapi:
{
rating: 4.2
}
Kita bisa menggunakan unary plus:
+readInputFieldValue("rating")
Misalnya:
+"4.2"
hasilnya:
4.2
Jadi:
movie.rating = +readInputFieldValue("rating");
13. Hal yang sama untuk release year
Misalnya user memasukkan:
2022
.value menghasilkan:
"2022"
Kita ingin:
2022
Maka:
movie.releaseYear =
+readInputFieldValue("release-year");
Sehingga object:
{
rating: 4.2,
releaseYear: 2022
}
bukan:
{
rating: "4.2",
releaseYear: "2022"
}
14. Kenapa tipe data ini penting?
Karena sebelumnya kita melakukan sorting:
movies.sort((a, b) => {
return a.rating - b.rating;
});
Kalau rating adalah String:
"4.2" - "3.5"
JavaScript masih bisa melakukan coercion dalam operasi -.
Tetapi secara desain data, lebih baik rating memang disimpan sebagai:
Number
Begitu juga:
releaseYear
harus Number.
Jadi kita menjaga konsistensi data:
name
↓
String
description
↓
String
rating
↓
Number
releaseYear
↓
Number
genre
↓
Array
15. Membuat object movie kosong
Lecture kemudian melakukan:
let newMovie = {};
Artinya kita membuat object kosong.
Awalnya:
{}
Kemudian kita isi property satu per satu.
Misalnya:
newMovie.name = "Mission Impossible";
menjadi:
{
name: "Mission Impossible"
}
Kemudian:
newMovie.description = "Some description";
menjadi:
{
name: "Mission Impossible",
description: "Some description"
}
Dan seterusnya.
16. Function readFormData()
Lecture memisahkan pekerjaan membaca form ke function:
function readFormData(movie) {
movie.name = readInputFieldValue("name");
movie.description =
readInputFieldValue("description");
movie.rating =
+readInputFieldValue("rating");
movie.releaseYear =
+readInputFieldValue("release-year");
movie.genre =
getSelectedCheckboxValue("genre");
return movie;
}
Ini desain yang bagus karena:
createMovie()mengurus proses membuat movie, sedangkanreadFormData()khusus mengurus membaca form.
17. Perhatikan parameter movie
Function:
function readFormData(movie) {
menerima object.
Kemudian kita panggil:
let newMovie = {};
newMovie = readFormData(newMovie);
Jadi:
newMovie
↓
{}
↓
readFormData(newMovie)
↓
movie parameter
↓
isi property
↓
return movie
↓
newMovie
18. Kenapa object bisa berubah?
Ini berhubungan langsung dengan materi sebelumnya tentang reference type.
Misalnya:
let newMovie = {};
Kemudian:
readFormData(newMovie);
Parameter movie mengarah ke object yang sama.
Mental model sederhananya:
newMovie ───────┐
↓
{}
↑
movie
Ketika:
movie.name = "Mission Impossible";
object yang sama berubah:
newMovie ───────┐
↓
{
name: "Mission Impossible"
}
↑
movie
Itulah kenapa property newMovie ikut berubah.
19. Mengisi property name
Code:
movie.name = readInputFieldValue("name");
Alurnya:
<input id="name">
↓
readInputFieldValue("name")
↓
document.getElementById("name")
↓
.value
↓
"Mission Impossible"
↓
movie.name = "Mission Impossible"
20. Mengisi description
Sama:
movie.description =
readInputFieldValue("description");
Misalnya user memasukkan:
This is a movie description.
hasil:
movie.description =
"This is a movie description.";
21. Mengisi rating
movie.rating =
+readInputFieldValue("rating");
Misalnya:
form
↓
"4.2"
↓
+"4.2"
↓
4.2
Object:
{
rating: 4.2
}
22. Mengisi release year
movie.releaseYear =
+readInputFieldValue("release-year");
Misalnya:
"2022"
↓
+ "2022"
↓
2022
23. Bagian yang sedikit lebih sulit: genre
Genre berbeda.
Kenapa?
Karena genre menggunakan checkbox.
Misalnya:
<input type="checkbox" name="genre" value="action">
<input type="checkbox" name="genre" value="drama">
<input type="checkbox" name="genre" value="comedy">
User bisa memilih:
☑ action
☑ drama
☐ comedy
Kita ingin mendapatkan:
["action", "drama"]
24. Kenapa tidak cukup menggunakan .value?
Kalau kita punya:
document.getElementById(...).value
itu cocok untuk satu input tertentu.
Tetapi genre punya banyak checkbox:
action
drama
comedy
sci-fi
...
Kita perlu:
- mendapatkan semua checkbox genre
- mengecek mana yang dicentang
- mengambil
.value - memasukkannya ke Array
25. getElementsByName()
Lecture menggunakan:
document.getElementsByName("genre");
Kenapa name?
Karena HTML checkbox-nya mempunyai:
name="genre"
Misalnya:
<input type="checkbox" name="genre" value="action">
<input type="checkbox" name="genre" value="drama">
<input type="checkbox" name="genre" value="comedy">
Maka:
document.getElementsByName("genre")
mengambil semua element yang memiliki name="genre".
Hasilnya adalah kumpulan element, bukan satu element.
26. NodeList
Hasil:
let checkboxes =
document.getElementsByName("genre");
adalah NodeList.
Misalnya:
checkboxes
│
├── checkbox action
├── checkbox drama
├── checkbox comedy
└── checkbox sci-fi
Catatan penting:
NodeList mirip Array karena bisa di-loop dan memiliki beberapa method seperti
forEach(), tetapi secara teknis bukan Array.
27. Menyiapkan Array kosong
Lecture membuat:
let selectedValues = [];
Awalnya:
[]
Kemudian setiap genre yang dipilih akan dimasukkan:
selectedValues.push(...)
Misalnya user memilih:
☑ action
☑ drama
prosesnya:
[]
↓ action checked
["action"]
↓ drama checked
["action", "drama"]
28. Loop menggunakan forEach()
Kemudian:
checkboxes.forEach((checkbox) => {
...
});
Artinya:
Periksa setiap checkbox satu per satu.
Misalnya ada:
action
drama
comedy
sci-fi
maka:
iteration 1 → action
iteration 2 → drama
iteration 3 → comedy
iteration 4 → sci-fi
29. .checked
Ini bagian penting:
if (checkbox.checked) {
checked menghasilkan Boolean:
true
atau:
false
Contoh:
☑ Action
maka:
checkbox.checked // true
Sedangkan:
☐ Comedy
maka:
checkbox.checked // false
30. .value vs .checked
Ini sering membingungkan.
.value
Menjawab:
“Nilai dari checkbox ini apa?”
Contoh:
<input
type="checkbox"
name="genre"
value="action"
>
maka:
checkbox.value
hasil:
"action"
.checked
Menjawab:
“Checkbox ini sedang dipilih atau tidak?”
Hasil:
true
atau:
false
Jadi:
value
↓
"action"
checked
↓
true
31. Logic getSelectedCheckboxValue()
Kurang lebih:
function getSelectedCheckboxValue(elementName) {
let selectedValues = [];
let checkboxes =
document.getElementsByName(elementName);
checkboxes.forEach((checkbox) => {
if (checkbox.checked) {
selectedValues.push(checkbox.value);
}
});
return selectedValues;
}
Sekarang mari kita jalankan dengan contoh.
32. Contoh checkbox
HTML:
<input
type="checkbox"
name="genre"
value="action"
checked
>
<input
type="checkbox"
name="genre"
value="drama"
checked
>
<input
type="checkbox"
name="genre"
value="comedy"
>
Panggil:
getSelectedCheckboxValue("genre");
Iterasi 1
action
checkbox.checked
hasil:
true
Maka:
selectedValues.push("action");
Array:
["action"]
Iterasi 2
drama
checked:
true
Maka:
selectedValues.push("drama");
Array:
["action", "drama"]
Iterasi 3
comedy
checked:
false
Tidak masuk ke if.
Array tetap:
["action", "drama"]
Return
return selectedValues;
hasil:
["action", "drama"]
33. Jadi readFormData() akhirnya menghasilkan object
Misalnya user mengisi:
Name:
Mission Impossible
Description:
Some test description
Rating:
4
Release Year:
2012
Genre:
action
drama
Maka:
let newMovie = {};
newMovie = readFormData(newMovie);
menghasilkan:
{
name: "Mission Impossible",
description: "Some test description",
rating: 4,
releaseYear: 2012,
genre: ["action", "drama"]
}
Perhatikan tipe datanya:
| Property | Type |
|---|---|
name | String |
description | String |
rating | Number |
releaseYear | Number |
genre | Array |
34. Kenapa readFormData() melakukan return movie?
Di akhir:
return movie;
Kemudian:
newMovie = readFormData(newMovie);
Jadi object yang sudah diisi dikembalikan.
Secara konsep:
{}
↓
readFormData()
↓
{
name: "...",
description: "...",
rating: 4,
releaseYear: 2012,
genre: [...]
}
↓
newMovie
35. Sekarang kita masuk ke createMovie()
Function utamanya kurang lebih:
function createMovie(event) {
event.preventDefault();
let newMovie = {};
newMovie = readFormData(newMovie);
movies.push(newMovie);
hideCreateMovieModal();
renderAllMovies(movies);
}
Ini adalah inti seluruh lecture.
Mari kita pecah satu per satu.
36. Kenapa menggunakan submit, bukan click?
Form memiliki:
<form id="create-movie-form">
Kita bisa mendengarkan:
createMovieForm.addEventListener(
"submit",
createMovie
);
Jadi ketika user submit form:
FORM
↓
submit event
↓
createMovie()
Tombol Create Movie yang berada di dalam form menyebabkan form melakukan submit.
37. preventDefault()
Ini sudah kamu pelajari sebelumnya.
Secara default, ketika form HTML di-submit:
submit
↓
browser melakukan default action
↓
page reload / navigation
Kita tidak mau itu.
Karena aplikasi kita ingin diproses menggunakan JavaScript tanpa reload.
Maka:
event.preventDefault();
Artinya:
“Browser, jangan lakukan aksi default dari submit ini.”
38. preventDefault() bukan menghentikan event
Ini penting dibedakan.
event.preventDefault();
berarti:
hentikan aksi default browser.
Bukan:
hentikan event bubbling.
Untuk bubbling kita menggunakan:
event.stopPropagation();
Jadi:
| Method | Fungsi |
|---|---|
preventDefault() | mencegah aksi default browser |
stopPropagation() | menghentikan event propagation |
Contoh:
Submit form
│
├── default browser action
│ ↓
│ reload page
│
└── event propagation
preventDefault() hanya mencegah bagian default action.
39. Membuat movie object
Setelah:
event.preventDefault();
kita buat:
let newMovie = {};
Kemudian:
newMovie = readFormData(newMovie);
Sekarang:
newMovie
sudah berisi semua data.
40. Memasukkan movie ke movies
Inilah bagian penting:
movies.push(newMovie);
Misalnya sebelumnya:
movies = [
movieA,
movieB,
movieC
];
Setelah:
movies.push(newMovie);
menjadi:
movies = [
movieA,
movieB,
movieC,
newMovie
];
41. Kenapa menggunakan push()?
Karena movies adalah Array dan kita ingin:
menambahkan satu element di bagian akhir Array.
Itulah fungsi:
push()
Ingat cheat sheet:
push() → tambah di belakang
pop() → hapus dari belakang
unshift() → tambah di depan
shift() → hapus dari depan
Dalam kasus create movie:
movies.push(newMovie);
sangat cocok.
42. Ini juga memperlihatkan konsep source of truth
Ini konsep yang sangat penting dari project ini.
Jangan hanya membuat card HTML baru.
Misalnya jangan hanya:
movieListSection.insertAdjacentHTML(...);
Karena kalau kita hanya mengubah UI, Array movies tidak berubah.
Nanti ketika:
renderAllMovies(movies);
dipanggil lagi, movie baru bisa hilang.
Jadi prinsipnya:
DATA
│
movies[]
│
↓
RENDER
│
↓
UI
Kalau ingin menambah movie:
new movie
↓
movies.push()
↓
movies berubah
↓
renderAllMovies()
↓
UI berubah
43. Kenapa form ditutup setelah berhasil?
Setelah:
movies.push(newMovie);
kita:
hideCreateMovieModal();
Karena proses create sudah selesai.
Alurnya:
User submit
↓
movie dibuat
↓
movie masuk array
↓
form ditutup
44. Kenapa harus render ulang?
Karena movies sudah berubah.
Sebelum:
movies = [
movie1,
movie2
];
Setelah:
movies = [
movie1,
movie2,
movie3
];
Tetapi perubahan Array tidak otomatis membuat HTML berubah.
Jadi kita harus:
renderAllMovies(movies);
45. Ini konsep yang sangat penting
JavaScript tidak otomatis berpikir:
“Oh, Array berubah, berarti tampilan HTML harus berubah.”
Tidak.
Kalau kita melakukan:
movies.push(newMovie);
yang berubah adalah data.
DOM masih seperti sebelumnya sampai kita melakukan rendering.
Jadi:
movies.push(newMovie)
↓
DATA berubah
renderAllMovies(movies)
↓
UI berubah
46. Hubungan dengan fitur Delete sebelumnya
Kamu sebenarnya sudah melihat pola yang sama pada Delete.
Delete:
findIndex()
↓
splice()
↓
movies berubah
↓
renderAllMovies()
↓
UI berubah
Create:
readFormData()
↓
push()
↓
movies berubah
↓
renderAllMovies()
↓
UI berubah
Jadi sekarang mulai terlihat pola project-nya.
47. Create vs Delete
| Fitur | Manipulasi Array |
|---|---|
| Create Movie | push() |
| Delete Movie | splice() |
| Filter Genre | filter() |
| Search | filter() + includes() |
| Find Details | find() |
| Find posisi movie | findIndex() |
| Sort | sort() |
| Render semua | forEach() |
Ini sebenarnya inti besar project CIN/Cinix.
48. Full flow Create Movie
Sekarang kita satukan semuanya.
HEADER
│
│ click
↓
showCreateMovieModal()
│
↓
remove("hidden")
│
↓
FORM MUNCUL
│
│
user mengisi
│
↓
klik Create
│
↓
submit event
│
↓
createMovie(event)
│
↓
event.preventDefault()
│
↓
newMovie = {}
│
↓
readFormData(newMovie)
│
┌────────┼─────────┐
↓ ↓ ↓
name rating genre
│ │ │
value Number checkbox
│ │ │
└────────┼─────────┘
↓
newMovie object
│
↓
movies.push(newMovie)
│
↓
hideCreateMovieModal()
│
↓
renderAllMovies(movies)
│
↓
MOVIE MUNCUL
49. Kenapa lecture membuat beberapa helper function?
Kita punya:
showCreateMovieModal()
hideCreateMovieModal()
createMovie()
readFormData()
readInputFieldValue()
getSelectedCheckboxValue()
Mungkin awalnya terlihat banyak.
Tapi sebenarnya masing-masing punya tanggung jawab berbeda.
showCreateMovieModal()
Tugas:
tampilkan form.
hideCreateMovieModal()
Tugas:
sembunyikan form.
createMovie()
Tugas:
mengatur keseluruhan proses create movie.
readFormData()
Tugas:
membaca seluruh data form dan memasukkannya ke object.
readInputFieldValue()
Tugas:
membaca value satu input berdasarkan ID.
getSelectedCheckboxValue()
Tugas:
mengambil semua checkbox yang dipilih.
Ini adalah contoh separation of concerns.
50. Analogi sederhana
Bayangkan kamu punya restoran.
createMovie() adalah manager.
Dia tidak melakukan semuanya sendiri.
Dia meminta:
Manager
│
├── "Baca data customer"
│ ↓
│ readFormData()
│
├── "Baca input tertentu"
│ ↓
│ readInputFieldValue()
│
├── "Baca checkbox"
│ ↓
│ getSelectedCheckboxValue()
│
└── "Tambahkan ke daftar"
↓
movies.push()
Dengan cara ini code lebih mudah dipahami dan digunakan kembali.
51. getElementsByName() vs getElementById()
Ini juga penting untuk kamu hafalkan.
getElementById()
Digunakan ketika kita ingin satu element berdasarkan ID.
document.getElementById("name");
Misalnya:
<input id="name">
getElementsByName()
Digunakan ketika kita ingin mendapatkan semua element dengan name tertentu.
document.getElementsByName("genre");
Misalnya:
<input name="genre">
<input name="genre">
<input name="genre">
hasilnya:
[element1, element2, element3]
52. Kenapa genre menggunakan name, bukan ID?
Karena setiap checkbox membutuhkan ID yang berbeda kalau memakai ID:
<input id="action">
<input id="drama">
<input id="comedy">
Tetapi mereka bisa mempunyai name yang sama:
<input name="genre" value="action">
<input name="genre" value="drama">
<input name="genre" value="comedy">
Jadi:
ID
↓
identitas unik element
name
↓
bisa digunakan untuk mengelompokkan beberapa element
53. Hubungan dengan materi sebelumnya tentang form
Sebelumnya kamu belajar:
Text input
input.value
Select
select.value
Radio
radio.value
radio.checked
Checkbox
checkbox.value
checkbox.checked
Lecture ini menggabungkan semuanya.
54. Hal yang menarik: .value selalu perlu diperhatikan tipenya
Misalnya:
let name = input.value;
hasil:
"Mission Impossible"
String.
Rating:
let rating = input.value;
hasil:
"4"
String.
Jadi:
+input.value
menjadi:
4
Number.
55. Kenapa genre tidak menggunakan +?
Karena:
checkbox.value
memang kita inginkan sebagai String:
"action"
"drama"
"comedy"
Jadi:
selectedValues.push(checkbox.value);
sudah benar.
Tidak perlu:
+checkbox.value
karena kita tidak ingin:
+"action"
56. Hasil akhirnya
Misalnya user mengisi:
Movie Name:
Mission Impossible
Description:
Some test description
Rating:
4
Release Year:
2012
Genre:
☑ action
☑ drama
☐ comedy
Maka object:
{
name: "Mission Impossible",
description: "Some test description",
rating: 4,
releaseYear: 2012,
genre: ["action", "drama"]
}
Kemudian:
movies.push(newMovie);
Array menjadi:
[
{
name: "Interstellar",
...
},
{
name: "Bad Boys",
...
},
{
name: "Mission Impossible",
description: "Some test description",
rating: 4,
releaseYear: 2012,
genre: ["action", "drama"]
}
]
Kemudian:
renderAllMovies(movies);
menghasilkan card baru di UI.
57. Satu hal yang perlu kamu sadari: object baru belum tentu punya id
Di project sebelumnya setiap movie memiliki:
id
yang digunakan untuk:
showMovieDetails(movie.id)
dan:
deleteMovie(movie.id)
Kalau newMovie hanya dibuat:
let newMovie = {};
kemudian diisi:
name
description
rating
releaseYear
genre
maka object tersebut belum memiliki:
id
Ini berarti, jika kode project persis seperti caption, ada hal yang perlu diperhatikan: movie baru idealnya juga mendapatkan ID unik sebelum dimasukkan ke movies.
Misalnya:
newMovie.id = ...
Cara membuat ID unik bisa dibahas sesuai implementasi project/course berikutnya. Jangan asal menggunakan index array sebagai ID karena index bisa berubah setelah splice().
Ini contoh kecil di mana kita perlu membedakan:
index array
≠
ID object
58. Ada juga kemungkinan image belum diisi
Movie awal memiliki:
{
image: "images/movie.jpg"
}
Sedangkan form yang dijelaskan lecture hanya meminta:
- name
- description
- rating
- release year
- genre
Kalau image tidak diisi, helper sebelumnya:
displayMovieBanner(movie.image)
akan menggunakan:
"images/not-found.jpg"
karena:
movie.image || "images/not-found.jpg"
Jadi project tetap bisa menampilkan default image.
59. Mengapa lecture ini penting?
Karena sekarang kamu tidak hanya membaca Array, tetapi sudah bisa melakukan CRUD sederhana.
CRUD:
C = Create
R = Read
U = Update
D = Delete
Project ini sudah memiliki sebagian besar konsep:
Create
movies.push(newMovie);
Read
renderAllMovies(movies);
dan:
movies.find(...)
Delete
movies.splice(index, 1);
Update
Belum menjadi fokus utama di lecture ini, tetapi konsepnya nanti bisa berupa:
movie.name = newName;
60. Cheat sheet project CIN/Cinix
Ini bagian yang menurutku paling bagus untuk kamu simpan.
┌─────────────────────────────────────────────┐
│ ARRAY METHODS │
├─────────────────────────────────────────────┤
│ forEach() → lakukan sesuatu untuk semua │
│ map() → ubah semua → Array baru │
│ filter() → pilih yang memenuhi kondisi │
│ find() → cari satu object │
│ findIndex() → cari posisi/index │
│ sort() → urutkan │
│ push() → tambah di belakang │
│ splice() → hapus/ubah isi Array │
│ includes() → cek apakah ada │
└─────────────────────────────────────────────┘
Dan untuk String:
┌─────────────────────────────────────────────┐
│ STRING METHODS │
├─────────────────────────────────────────────┤
│ split() → String → Array │
│ join() → Array → String │
│ slice() → ambil sebagian │
│ substring() → ambil sebagian │
│ at() → ambil karakter │
│ toUpperCase() → huruf besar │
│ toLowerCase() → huruf kecil │
│ trim() → hapus whitespace luar │
│ repeat() → ulangi String │
│ concat() → gabungkan String │
│ padStart() → padding dari depan │
│ padEnd() → padding dari belakang │
│ includes() → cek apakah mengandung │
└─────────────────────────────────────────────┘
61. Pola yang harus kamu pahami dari seluruh project
Sebenarnya semua fitur project ini mengikuti pola yang sama:
USER ACTION
↓
EVENT
↓
FUNCTION
↓
MANIPULATE DATA
↓
RENDER UI
Search
input
↓
filter()
↓
render
Filter genre
radio
↓
filter()
↓
render
Sort
button
↓
sort()
↓
render
Details
button
↓
find()
↓
buat HTML
↓
modal
Delete
button
↓
findIndex()
↓
splice()
↓
render
Create
form
↓
read values
↓
buat object
↓
push()
↓
render
Jadi sebenarnya project ini bukan kumpulan code yang acak. Ada pola berpikir yang konsisten.
62. Kesimpulan paling penting
Kalau harus diringkas menjadi satu mental model:
Form bukan langsung membuat UI movie. Form menghasilkan data. Data dimasukkan ke
movies. Setelah data berubah, kita render ulang UI.
Secara visual:
FORM
│
│ .value / .checked
↓
FORM DATA
│
↓
newMovie object
│
↓
movies.push(newMovie)
│
↓
movies Array
│
↓
renderAllMovies(movies)
│
↓
DOM
│
↓
MOVIE CARD
Dan ini melanjutkan prinsip yang sudah kamu pelajari pada Delete:
SOURCE OF TRUTH
│
movies[]
│
┌──────────┴──────────┐
↓ ↓
CREATE DELETE
↓ ↓
push() splice()
│ │
└──────────┬──────────┘
↓
movies berubah
↓
renderAllMovies()
↓
UI
🔑 Yang paling wajib kamu ingat dari lecture ini
formmemiliki eventsubmit.event.preventDefault()mencegah reload/default action form..valuedigunakan untuk membaca nilai input..valuedari form biasanya berupa String, sehingga angka perlu dikonversi.- Unary
+bisa mengubah"4.2"→4.2. - Checkbox perlu diperiksa dengan
.checked. .valuecheckbox memberikan nilai seperti"action".getElementsByName("genre")mengambil semua checkbox denganname="genre".forEach()digunakan untuk memeriksa setiap checkbox.selectedValues.push(checkbox.value)mengumpulkan genre yang dipilih.movies.push(newMovie)menambahkan movie ke data utama.- Setelah data berubah,
renderAllMovies(movies)diperlukan agar UI ikut berubah. - Data
moviesadalah source of truth; UI adalah hasil render dari data tersebut.
Kalau kamu sudah memahami alur form → object → push() → render, berarti kamu sebenarnya sudah memahami fondasi yang cukup penting untuk membuat aplikasi JavaScript interaktif sederhana.