Anda di halaman 1dari 67

BELAJ

AR
KNOCKOUT
JS
Belajar KnockoutJS

Anggie Bratadinata
www.masputih.com

©2013
©2013 Anggie Bratadinata | masputih.com

Daftar Isi

1 Introduksi 1
1.1 KnockoutJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 MVVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Instalasi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 ViewModel 5
2.1 Data Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Observable & Computed Observable . . . . . . . . . . . . . . . . . . . . . . 9
Manual Subscription . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Observable Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Notifikasi Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3 Data Binding 17
3.1 DOM & Input Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Click . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Visible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Style dan CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2 Form Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Checked, Enable, & Disable . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3 Control-flow Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
if & ifnot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
foreach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

ii
DAFTAR ISI iii

3.4 Template Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4 Contoh : Shopping Cart 45


4.1 Planning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.2 Implementasi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

5 Penutup 57
©2013 Anggie Bratadinata | masputih.com

Bab 1

Introduksi

Saat ini banyak framework atau library JavaScript yang bisa kita pake untuk bikin ap-
likasi web interaktif. Kalo Anda ngikutin perkembangan JavaScript, sekarang kita bisa
pake Backbone, Angular, Dojo, dan lain-lain. Hampir setiap bulan muncul library atau
framework baru.
Sebelum pilih library, kita perlu tahu tujuan atau fokus masing-masing library karena
setiap library punya fokus tertentu. Sebagai contoh, JQuery fokus ke manipulasi el-
emen DOM. Backbone, Knockout, dan Angular menyediakan struktur untuk aplikasi.
Karena perbedaan fokus ini, hampir pasti semua aplikasi yang pake JavaScript butuh
lebih dari satu library.
Untuk bikin produk akhir dan kode yang berkualitas, kita nggak bisa asal pilih. Ng-
gak pas kalo kita pake JQuery untuk membuat struktur aplikasi, karena fokus JQuery
adalah manipulasi DOM. Bukannya nggak mungkin, tapi karena fokusnya beda, sekalipun
produk akhir yang kita hasilkan berkualitas, kode yang kita tulis pasti terlalu ruwet,
penuh hack di sana-sini.

1
2 BAB 1. INTRODUKSI

1.1 KnockoutJS

Knockout, selanjutnya disingkat KO, dibuat kira-kira 2 tahun lalu oleh Steven Sander-
son1 , seorang programer spesialis teknologi .NET. Sekarang KO bukan lagi proyek
pribadi pembuatnya, tapi udah jadi proyek komunitas. Banyak programer lain yang
ikut berkontribusi baik dalam hal pengembangan core maupun pembuatan ekstensi
(plugin).
Mungkin ada pertanyaan,"Ngapain pake library lagi? JQuery udah cukup.". Kembali ke
teks sebelumnya, JQuery fokus pada manipulasi DOM. Untuk aplikasi sederhana atau
sekedar bikin cantik halaman web, mungkin udah cukup. Kalo kita bikin aplikasi yang
relatif rumit, dengan banyak data, operasi CRUD, elemen visual yang kompleks, dan
lain-lain, kalo hanya pake JQuery bisa dipastiin kode yang kita tulis terlalu rumit dan
nggak maintainable. Di sini peran library yang nyediain struktur seperti KO, Backbone,
dan lain-lain.

1.2 MVVM

MVVM (Model-View-ViewModel) adalah nama sebuah design pattern2 untuk pengem-


bangan web client. Pattern atau struktur ini awalnya populer di kalangan programer
.NET, utamanya mereka yang suka bikin aplikasi Silverlight. Sebagai informasi, pro-
gramer Flex juga pasti nggak asing dengan pattern ini biarpun banyak yang nggak
sadar ,.
MVVM membagi kode dalam 3 bagian yaitu:
• View
• Model
• ViewModel
1
http://blog.stevensanderson.com
2
http://id.wikipedia.org/wiki/Pola_desain
1.3. INSTALASI 3

View adalah bagian visual (HTML) yang tugasnya nampilin data dan berinteraksi den-
gan pengguna. Model adalah representasi data yang digunakan oleh aplikasi. View-
Model berfungsi sebagai otak aplikasi yang bertugas untuk:
• Update view
• Memproses input dari user
• Update model atau baca data dari model
Dalam banyak kasus, Model bersifat opsional karena seringkali data bisa kita jadiin
satu dengan ViewModel. Jadi MVVM sering juga disebut MV*.
Alur kerja MVVM bisa digambarkan seperti berikut:

Gambar 1.1: MVVM

Kalo Anda pernah belajar pattern MVC (Model-View-Controller) pasti Anda bisa liat
kemiripan antara ViewModel dan Controller. Keduanya memang mirip, salah satu be-
danya adalah, dalam MVC, View nggak perlu tahu kontrolernya tapi kontroler perlu
tahu View sedangkan MVVM adalah sebaliknya, View perlu tahu kontrolernya (View-
Model) tetapi VM bisa jadi nggak tahu apa-apa mengenai View.

1.3 Instalasi

KO bisa kita unduh dari situs www.knockoutjs.com atau GitHub3 . Untuk keperluan be-
lajar atau selama proses development, sebaiknya kita pilih versi debug dari halaman
3
https://github.com/knockout/knockout
4 BAB 1. INTRODUKSI

http://knockoutjs.com/downloads/index.html. Versi terbaru KO waktu buku ini di-


tulis adalah versi 2.2.1.

Listing 1.1: Template HTML

1 <!doctype html>
2 <head></head>
3 <body>
4

5 <script src="knockout-2.2.1.js"></script>
6 </body>
7 </html>
©2013 Anggie Bratadinata | masputih.com

Bab 2

ViewModel

ViewModel (VM) sebenarnya adalah sebuah objek. Bedanya dengan objek "biasa"
adalah VM berpasangan dengan HTML lewat data-binding, bisa dengan seluruh ha-
laman atau elemen tertentu aja, dan bisa mengubah fungsi (behavior) atau tampilan
elemen HTML tersebut. Untuk bikin VM kita bisa pake sintaks objek literal atau con-
structor function seperti contoh di bawah.

Listing 2.1: ViewModel dengan Objek Literal


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title></title>
5 </head>
6 <body>
7
8 <script src="knockout-2.2.1.debug.js"></script>
9 <script>
10
11 //objek literal
12 var vm = {
13 userName:'Bobo',
14 age :31
15 }
16
17 ko.applyBindings(vm);

5
6 BAB 2. VIEWMODEL

18
19 </script>
20 </body>
21 </html>
22
23

Untuk menggunakan constructor function, kita ganti definisi objek vm dalam kode di
atas. Karena constructor function diinstansiasi dengan keyword new , kita ganti juga
argumen untuk ko.applyBindings() .

Listing 2.2: ViewModel dengan constructor function


1 //constructor function
2 var VM = function(){
3 var self = this;
4 self.userName = 'Bobo';
5 self.age = 31;
6 }
7
8 ko.applyBindings(new VM());
9

Kode ko.applyBindings() berfungsi untuk mengaktifkan KO. Function ini sebenarnya


punya parameter kedua yang sifatnya opsional dan hanya kita pake kalo kita ingin bikin
binding antara sebuah vm dengan sebuah elemen tertentu. Dalam Listing 2.2 di atas,
kita hanya pake satu parameter yang artinya kita melakukan binding antara vm dengan
elemen <body> .

Z Objek Literal vs Constructor Function

Mana yang lebih baik, objek literal atau constructor function? Construc-
tor function lebih fleksibel karena kita bisa bikin variabel & fungsi yang
bersifat private. Objek literal tetap bisa dipake tapi sebaiknya hanya
untuk VM yang sederhana.
2.1. DATA BINDING 7

2.1 Data Binding

Untuk bikin binding antara elemen HTML dengan ViewModel, kita pake deklarasi data-bind
sebagai salah satu atribut elemen HTML.

Listing 2.3: binding.html


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title></title>
5 <meta charset="utf-8">
6 </head>
7 <body>
8
9 <ul>
10 <li data-bind="text:userName">Nana</li>
11 <li data-bind="text:age">100</li>
12 </ul>
13
14 <script src="knockout-2.2.1.debug.js"></script>
15 <script>
16 //constructor function
17 function VM() {
18 var self = this;
19 self.userName = 'Bobo';
20 self.age = 31
21 }
22
23 var myVM = new VM();
24
25 ko.applyBindings(myVM);
26 </script>
27 </body>
28 </html>

Kalo kita buka file ini di browser, kita bisa liat isi dari elemen <li> berubah pada waktu
KO sudah aktif. Kita bisa liat prosesnya pake fasilitas debugger dari Firefox Developer
8 BAB 2. VIEWMODEL

Tool seperti Gambar 2.1 dan Gambar 2.2. Dalam Gambar 2.1, <li> masih berisi teks
yang kita tulis di HTML. Setelah KO aktif, isi <li> diganti oleh nilai myVM.userName
dan myVM.age .

Gambar 2.1: Elemen <li> sebelum KO aktif (breakpoint)

Gambar 2.2: Elemen <li> setelah KO aktif


2.2. OBSERVABLE & COMPUTED OBSERVABLE 9

Sekarang kita coba ganti nilai userName pake web console di Firebug. Ketik kode di
bawah terus tekan Enter.
> myVM.age = 22
Apa isi <li> berubah? Nggak. Kenapa? Karena properti age bukan berupa observ-
able. Artinya, perubahan nilai yang kita lakukan nggak diteruskan oleh KO ke elemen
<li> . Sama juga dengan properti userName .
Sekarang coba ganti definisi VM seperti berikut. Terus refresh Firefox.

Listing 2.4: Observable properties


1 function VM() {
2 var self = this;
3 self.userName = ko.observable('Bobo');
4 self.age = ko.observable(31);
5 }
6

Di web console, kita coba ganti nilai age & userName .


> myVM.age(11)
> myVM.userName('Toto')
Hasilnya, teks elemen <li> juga ikut berubah. Yay! ,
Apa yang kita liat disini adalah contoh dari "binding satu arah" di mana setiap pe-
rubahan nilai dalam ViewModel akan menyebabkan perubahan elemen HTML yang
bersangkutan.

2.2 Observable & Computed Observable

ko.observable adalah sebuah function yang memungkinkan kita membuat sebuah


properti dalam sebuah objek yang bisa diamati (observed) oleh objek lain, bisa elemen
HTML atau objek JavaScript. Objek yang diamati disebut observable sedangkan objek
yang mengamati disebut subscriber atau observer.
10 BAB 2. VIEWMODEL

¢ Penting

Observable adalah sebuah function, jadi untuk mengakses nilai yang


ada di dalamnya kita harus pake '()' seperti kalo kita mengeksekusi
function lainnya.
Untuk membaca nilai myVM.age kita tulis myVM.age() & untuk mengubah
nilainya, myVM.age(55).

Computed Observable adalah observable yang merespon perubahan observable lain.


Kalo observable yang diamati berubah nilainya, computed observable otomatis diek-
sekusi & hasilnya diteruskan oleh KO ke elemen HTML pasangannya.
Dalam contoh berikut, teks di kanan "Penjumlahan" dan "Perkalian" adalah nilai com-
puted observable sum dan mul yang merupakan hasil penjumlahan dan perkalian
firstNum dengan secondNum .

Listing 2.5: Computed Observable


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title></title>
5 <meta charset="utf-8">
6 </head>
7 <body>
8
9 <ul>
10 <li>Penjumlahan: <span data-bind="text:sum" ></span>
↪</li>
11 <li>Perkalian: <span data-bind="text:mul"></span></li>
12 </ul>
13
14 <script src="knockout-2.2.1.debug.js"></script>
15 <script>
16 //constructor function
17 function VM() {
18 var self = this;
19 self.firstNum = ko.observable(0);
2.2. OBSERVABLE & COMPUTED OBSERVABLE 11

20 self.secondNum = ko.observable(0);
21
22 self.sum = ko.computed(function(){
23 return self.firstNum() + self.secondNum();
24 })
25
26 self.mul = ko.computed(function(){
27 return self.firstNum() * self.secondNum();
28 })
29 }
30
31 var myVM = new VM();
32
33 ko.applyBindings(myVM);
34 </script>
35 </body>
36 </html>

Coba ubah nilai firstNum dan secondNum di web console. Teks yang ditampilin juga
akan berubah.
> myVM.firstNum(10)
> myVM.secondNum(20)

Manual Subscription

Dalam membuat aplikasi, kadang kita perlu merespon perubahan sebuah observable
tapi nggak perlu mengubah elemen UI. Dalam kasus seperti ini kita punya dua alter-
natif.
1. Bikin computed observable tanpa bikin data-binding
2. Merespon secara manual
Opsi pertama nggak efisien karena biarpun nggak ada data-binding, waktu ada pe-
rubahan nilai observable, KO akan berusaha mencari elemen yang punya atribut data-
binding yang berhubungan.
12 BAB 2. VIEWMODEL

Observable nyediain API untuk menghandel perubahan secara manual melalui func-
tion subscribe() . Function ini memerlukan satu argumen berupa sebuah function/-
callback yang nantinya akan menerima nilai baru si observable sebagai argumen.
Dalam contoh berikut, kita nggak nampilin teks dalam HTML, tapi hanya nampilin alert
dialog. Kita nggak perlu pake observable karena nggak ada elemen HTML untuk bind-
ing, cukup pake manual subscription.

Listing 2.6: Subscription

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title></title>
5 <meta charset="utf-8">
6 </head>
7 <body>
8

9 <script src="knockout-2.2.1.debug.js"></script>
10 <script>
11 function VM() {
12 var self = this;
13

14 self.firstNum = ko.observable(0);
15 self.firstNum.subscribe(function(newValue){
16 alert(newValue * 100);
17 })
18 }
19

20 var myVM = new VM();


21

22 ko.applyBindings(myVM);
23 </script>
24 </body>
25 </html>
2.3. OBSERVABLE ARRAY 13

Kita coba ubah nilai firstNum .


> myVM.firstNum(10)
Hasilnya seperti gambar berikut.

Gambar 2.3: Subscribable alert

2.3 Observable Array

Berikutnya adalah Observable Array, biar nggak banyak ngetik kita sebut OA aja.
Sesuai dengan namanya, OA adalah observable yang berisi sebuah Array . Ob-
servable ini akan mendeteksi perubahan struktur array (panjang & urutan elemen) &
memberitahu semua subscriber/observer kalo strukturnya berubah.
OA hanya mendeteksi perubahan struktur & nggak mendeteksi perubahan atribut dari
objek yang ada di dalam array. Selain itu, OA juga nyediain function tambahan un-
14 BAB 2. VIEWMODEL

tuk memanipulasi array. Semua subscriber akan mendapat pemberitahuan secara


otomatis selama kita memanipulasi array pake function yang disediakan OA.
Dalam Listing 2.7, kita tampilin panjang myVM.chars dengan cara binding antara ele-
men <p> dengan computed observable myVM.charCount .

Listing 2.7: Observable Array

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title></title>
5 <meta charset="utf-8">
6 </head>
7 <body>
8

9 <p data-bind="text:charCount"></p>
10

11 <script src="knockout-2.2.1.debug.js"></script>
12 <script>
13 function VM() {
14 var self = this;
15 self.chars = ko.observableArray([]);
16 self.charCount = ko.computed(function(){
17 return self.chars().length;
18 })
19 }
20 var myVM = new VM();
21

22 ko.applyBindings(myVM);
23 </script>
24 </body>
25 </html>

Terus kita coba manipulasi self.chars .


2.3. OBSERVABLE ARRAY 15

> myVM.chars.push('a')
> myVM.chars.push('b')
> myVM.chars.shift()
Hasilnya, teks elemen <p> berturut-turut: 1 , 2 , 1 .

Notifikasi Manual

Sekarang kita coba akses langsung array di dalam myVM.chars , maksudnya nggak
lewat function yang disediain observableArray , tapi pake function dari Array . Per-
hatikan tanda kurung di belakang chars .
> myVM.chars().push('c')
Hasilnya, teks di elemen <p> nggak berubah. Kenapa? Karena kita langsung modi-
fikasi array yang ada di dalam OA myVM.chars . Akibatnya, myVM.charCount nggak
dieksekusi karena nggak ada notifikasi dari myVM.chars . Ini bukan bug, tapi salah
satu fitur KO yang bermanfaat untuk optimasi pemrosesan data dalam jumlah besar.
Manipulasi OA pake function yang disediain bisa bikin aplikasi kita lemot kalo banyak
data yang harus diproses karena setiap kali ada objek yang dimasukin atau dikeluarin,
OA akan mengirim notifikasi yang pasti langsung direspon oleh subscriber-nya. Kalo
datanya sedikit sih nggak masalah. Tapi kalo misalnya kita punya 100 objek yang harus
dimasukin OA, berarti ada 100 notifikasi & 100 respon. Bisa kena script timeout/crash.
Apalagi kalo OA ini dipake untuk binding.
Kalo datanya banyak, lebih baik kalo kita pake akses langsung ke array jadi OA nggak
akan kirim notifikasi selama proses berjalan. Terus gimana supaya subscriber-nya
tahu? Gampang. Setelah proses selesai, tambahin satu baris kode lagi. Untuk contoh
di atas, kodenya seperti di bawah ini.
> myVM.chars.valueHasMutated()
Function valuHasMutated kita pake untuk kirim notifikasi secara manual ke semua
subscriber. Notifikasi yang dikirim berisi nilai/data terakhir yang dimiliki observable.
Function ini bukan hanya ada di OA tapi di semua observable. Jadi, KO kasih kita
pilihan, mau otomatis atau manual. Mana yang kita pilih, tergantung kebutuhan.
16 BAB 2. VIEWMODEL

Sampai di sini tentu Anda udah paham konsep dasar KnockoutJS. Nggak susah-susah
amat. Dalam bab selanjutnya kita akan belajar lebih banyak tentang data-binding.
©2013 Anggie Bratadinata | masputih.com

Bab 3

Data Binding

Data-binding bukan hanya untuk nampilin/ngerubah teks, tapi banyak sekali fungsinya.
KO nyediain banyak built-in binding untuk styling(css), form input, dan lain-lain. Kalo
diperlukan, kita juga bisa bikin custom binding sendiri. Dalam bab ini kita akan belajar
tentang beberapa built-in binding.
Ada beberapa macam binding dalam KO. Ada yang dipake untuk manipulasi DOM,
kondisional, templating, dan lain-lain. Binding nggak harus dilakukan antara elemen
HTML dengan observable, tapi bisa antara elemen HTML dengan function biasa.

3.1 DOM & Input Binding

Binding yang pertama adalah yang berhubungan dengan manipulasi DOM1 & event
untuk modifikasi elemen html & menghandel input dari user.

Click

Click binding kita pake untuk merespon event click . Mirip jQuery on('click')
. Sebagai contoh, dalam Listing 3.1 kita bikin binding antara elemen <a> dengan
1
Document Object Model

17
18 BAB 3. DATA BINDING

myVM.handleClick . Waktu <a> diklik, elemen p#news ditampilin atau disembun-


yiin lewat pengaturan nilai atribut class . Kalo atribut class bernilai hidden , p
disembunyiin. Kalo nilainya visible , p ditampilin.
Alurnya seperti Gambar 3.1.

Gambar 3.1: Alur Contoh Click Binding

Listing 3.1: Contoh Click-binding


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6
7 <style type="text/css">
8 .visible{
9 visibility: visible;
10 }
11 .hidden{
12 visibility: hidden;
13 }
14 </style>
15
16 </head>
17 <body>
18
3.1. DOM & INPUT BINDING 19

19 <h1>Miami Heat</h1>
20 <a href="#" data-bind="click:handleClick">Show/Hide</a>
21
22 <p id="news" class="hidden">
23 The White House says President Barack Obama has
↪congratulated the Miami Heat&#39;s head coach on winning
↪the NBA championship the second year in a row.
24 </p>
25
26 <script src="knockout-2.2.1.debug.js"></script>
27 <script>
28 function VM(){
29 var self = this;
30 var news = document.getElementById('news');
31
32 self.handleClick = function(){
33 var c = ( news.getAttribute('class') === 'visible')
↪? 'hidden':'visible'
34 news.setAttribute('class',c);
35 }
36 };
37
38 var vm = new VM();
39 ko.applyBindings(vm)
40 </script>
41 </body>
42 </html>

Hasilnya kurang lebih seperti berikut.

Gambar 3.2: Demo Click Binding Kondisi Awal


20 BAB 3. DATA BINDING

Gambar 3.3: Demo Click Binding setelah Show/Hide diklik

Text

Binding yang kedua adalah text binding. Binding ini kita pake untuk mengubah text
node sebuah elemen. Sebagai contoh, kita modifikasi kode Listing 3.1 di atas. Kita
buat teks elemen <a> berganti-ganti antara Show dan Hide . Kalo p#news dis-
embunyiin, teks <a> jadi Show . Kalo p#news lagi ditampilin, teks <a> jadi Hide
.

Gambar 3.4: Alur Demo Text Binding

Listing 3.2: Contoh Text-binding


1 <!DOCTYPE html>
3.1. DOM & INPUT BINDING 21

2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6
7 <style type="text/css">
8 .visible{
9 visibility: visible;
10 }
11 .hidden{
12 visibility: hidden;
13 }
14 </style>
15
16 </head>
17 <body>
18
19 <h1>Miami Heat</h1>
20 <a href="#" data-bind="click:handleClick">
21 <span data-bind="text:linkText"></span>
22 </a>
23
24 <p id="news" class="hidden">
25 The White House says President Barack Obama has
↪congratulated the Miami Heat&#39;s head coach on winning
↪the NBA championship the second year in a row.
26 </p>
27
28 <script src="knockout-2.2.1.debug.js"></script>
29 <script>
30 function VM(){
31 var self = this;
32 var news = document.getElementById('news');
33
34 self.linkText = ko.observable('Show');
35
36 self.handleClick = function(){
37 var c;
38 if( news.getAttribute('class') === 'visible'){
39 c = 'hidden'
40 self.linkText('Show');
22 BAB 3. DATA BINDING

41 }else{
42 c = 'visible'
43 self.linkText('Hide');
44 }
45
46 news.setAttribute('class',c);
47 }
48 };
49
50 var vm = new VM();
51 ko.applyBindings(vm)
52 </script>
53 </body>
54 </html>

Kita bikin elemen span sebagai child dari elemen <a> & kita bikin binding dengan
myVM.linkText seperti Listing 3.2 di bawah ini.
Hasilnya seperti Gambar 3.5 dan Gambar 3.6.

Gambar 3.5: Sebelum Show diklik.

Gambar 3.6: Sesudah Show diklik.


3.1. DOM & INPUT BINDING 23

Visible

Untuk mengatur visibility sebuah elemen, KO menyediakan binding bernama visible


. Jadi kode Listing 3.2 di atas bisa kita sederhanakan lagi seperti berikut.

Listing 3.3: Contoh Visible Binding


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <!-- nggak perlu CSS lagi -->
7 </head>
8 <body>
9
10 <h1>Miami Heat</h1>
11 <a href="#" data-bind="click:handleClick">
12 <span data-bind="text:linkText"></span>
13 </a>
14
15 <p id="news" data-bind="visible:showNews">
16 The White House says President Barack Obama has
↪congratulated the Miami Heat&#39;s head coach on winning
↪the NBA championship the second year in a row.
17 </p>
18
19 <script src="knockout-2.2.1.debug.js"></script>
20 <script>
21 function VM(){
22 var self = this;
23 self.showNews = ko.observable(false);
24 self.linkText = ko.computed(function(){
25 return self.showNews() ? 'Hide':'Show';
26 })
27 self.handleClick = function(){
28 self.showNews(!self.showNews());
29 }
30 };
31
24 BAB 3. DATA BINDING

32 var vm = new VM();


33 ko.applyBindings(vm)
34 </script>
35 </body>
36 </html>

Dalam listing di atas, nilai myVM.showNews berubah dari true ke false dan sebaliknya
setiap kali kita klik elemen <a> . Kita nggak butuh CSS lagi karena KO otomatis kasih
atribut style='visibility:hidden' atau style='visibility:visible' di elemen
p#news tergantung nilai myVM.showNews . Selain itu, myVM jadi lebih portable karena
nggak perlu referensi ke elemen p#news .

Z Info
Baris 28 dari Listing 3.3 di atas sama dengan :
if(self.showNews()){
self.showNews(false)
}else{
self.showNews(true)
}

Style dan CSS

KO juga menyediakan binding untuk memanipulasi atribut style & class . Untuk
atribut style , kita pake style binding sedangkan untuk atribut class , kita pake css
binding.

Listing 3.4: CSS & Style Binding


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6
7 <style type="text/css">
8 .big_box{
3.1. DOM & INPUT BINDING 25

9 width: 100%;
10 background-color: beige;
11 float:none;
12 }
13
14 .small_box{
15 width: 100px;
16 height: 50px;
17 background-color: aquamarine;
18 float:left;
19 text-align: center;
20 }
21 </style>
22
23 </head>
24 <body>
25 <!-- style binding -->
26 <h1 data-bind="style:{color:headerColor}">Miami Heat</h1>
27
28 <!-- css binding -->
29 <div data-bind="css:linkContainerStyle">
30 <a href="#" data-bind="click:handleClick">
31 <span data-bind="text:linkText"></span>
32 </a>
33 </div>
34
35 <p id="news" data-bind="visible:showNews">
36 The White House says President Barack Obama has
↪congratulated the Miami Heat&#39;s head coach on winning
↪the NBA championship the second year in a row.
37 </p>
38
39 <img src="heat.jpg" alt="" width='200px'/>
40
41 <script src="knockout-2.2.1.debug.js"></script>
42 <script>
43 function VM(){
44 var self = this;
45
46 self.showNews = ko.observable(false);
47
26 BAB 3. DATA BINDING

48 self.linkText = ko.computed(function(){
49 return self.showNews() ? 'Hide':'Show';
50 })
51
52 self.headerColor = ko.computed(function(){
53 return self.showNews() ? 'red':'black';
54 })
55
56 self.linkContainerStyle = ko.computed(function(){
57 return self.showNews() ? 'big_box':'small_box';
58 })
59
60 self.handleClick = function(){
61 self.showNews(!self.showNews());
62 }
63 };
64
65 var vm = new VM();
66 ko.applyBindings(vm)
67 </script>
68 </body>
69 </html>

Gambar 3.7: Sebelum Show diklik.


3.2. FORM INPUT 27

Gambar 3.8: Sesudah Show diklik

Warna elemen h1 diatur pake inline css. Nilai properti color dari inline css ini tergan-
tung nilai headerColor . Kalo nilainya red , atribut style berubah jadi style='color:red'
. Kalo nilainya black , jadi style='color:black' . Metode ini bisa dipake untuk
styling sederhana aja karena satu observable di VM hanya bisa dipake untuk ngeset
satu properti CSS. Untuk styling lebih dari satu properti, kita pake css-binding.

3.2 Form Input

Value

Value binding dipake untuk binding antara form input dengan VM. Kalo user masukin
input, otomatis nilai yang baru disimpen sama VM. Kalo VM diubah, otomatis elemen
input di-update. Binding ini bisa dipake untuk elemen yang punya atribut value yaitu
<input> , <textarea> , dan <select> .

Listing 3.5: Contoh Value Binding


1 <!DOCTYPE html>
2 <html lang="en">
28 BAB 3. DATA BINDING

3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 </head>
7 <body>
8
9 <input type="text" data-bind="value:message" />
10
11 <h2>Pesan yang diketik</h2>
12 <p data-bind="text:message"></p>
13
14 <script src="knockout-2.2.1.debug.js"></script>
15 <script>
16 function VM(){
17 var self = this;
18
19 self.message = ko.observable('');
20
21 };
22
23 var vm = new VM();
24 ko.applyBindings(vm)
25 </script>
26 </body>
27 </html>

Coba ketik teks di dalam text input terus tekan tombol Enter. Nilai vm.message akan
di-update sehingga teks di bawah h2 juga akan berubah karena dia pake text-binding
dengan vm.message .

Gambar 3.9: Input -> VM -> p


3.2. FORM INPUT 29

Kita coba update nilai vm.message pake konsol. Teks yang ada di dalam text input
dan di bawah h2 juga akan berubah.

Gambar 3.10: VM -> input

Real-time Update

Dalam demo di atas, kita perlu tekan tombol Enter untuk menyimpan teks. Apa bisa
disimpan secara real-time? Setiap huruf yang kita ketik di text input langsung dis-
impen di VM? Bisa. Kita pake binding lain yang namanya valueUpdate di belakang
value:message . Binding ini dipake untuk menentukan kapan value yang baru harus
disimpan sama VM. Kita ubah baris 9 jadi seperti di bawah ini.
<input type="text"
data-bind="value:message,valueUpdate:'afterkeyup'"/>
afterkeyup berarti kita ingin VM di-update setelah tombol dilepas. Opsi lainnya adalah
afterkeydown yang berarti langsung update pada waktu tombol ditekan.

Options

Options binding kita pake untuk elemen <select> .


30 BAB 3. DATA BINDING

Dalam Listing 3.6, kita bikin daftar kota & populasinya untuk komponen select . Daftar
ini berupa array berisi objek. Komponen select kita atur untuk nampilin properti
nama dari setiap objek pake optionsText:'nama' . Supaya objek yang dipilih disimpan
sebagai selectedCity , kita pake value:selectedCity . optionsCaption sifatnya
opsional & kita pake untuk nampilin teks kalo nggak ada objek yang dipilih.
Kalo kita pilih salah satu kota, informasi nama & populasinya kita tampilin dalam div
di bawah komponen select .

Listing 3.6: Contoh Options Binding


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 </head>
7 <body>
8
9 <select data-bind="options:data,
10 optionsText:'nama',
11 value:selectedCity,
12 optionsCaption:'Pilih kota'"></select>
13
14 <div data-bind="visible:selectedCity" style="background-
↪color: yellow;padding: 10px">
15 <h3>Populasi</h3>
16 <p><span data-bind="text:selectedCityName"></span>,
↪<span data-bind="text:selectedCityPopulation"></span></p>
17 </div>
18
19 <script src="knockout-2.2.1.debug.js"></script>
20 <script>
21
22 var populasi = [
23 {nama:'Jakarta',propinsi:'DKI Jakarta',populasi
↪:9607787},
24 {nama:'Surabaya',propinsi:'Jawa Timur',populasi
↪:2765487},
25 {nama:'Bandung',propinsi:'Jawa Barat',populasi
3.2. FORM INPUT 31

↪:2394873},
26 {nama:'Bekasi',propinsi:'Jawa Barat',populasi:2334871}
27 ];
28
29 function VM($data){
30 var self = this;
31 self.data = ko.observableArray($data);
32 self.selectedCity = ko.observable();
33
34 self.selectedCityName = ko.computed(function(){
35 return (self.selectedCity() !== undefined) ? self.
↪selectedCity().nama : 'Tidak ada yang dipilih';
36 });
37
38 self.selectedCityPopulation = ko.computed(function(){
39 return (self.selectedCity() !== undefined) ? self.
↪selectedCity().populasi : undefined;
40 })
41
42 };
43
44 var vm = new VM(populasi);
45 ko.applyBindings(vm)
46 </script>
47 </body>
48 </html>

Gambar 3.11: Pilih kota


32 BAB 3. DATA BINDING

Gambar 3.12: Tampilin info

Checked, Enable, & Disable

checked binding kita pake untuk untuk hapus atau set atribut checked di elemen radio
button & checkbox. Sama seperti value binding, enable & disable binding hanya bisa
kita pake untuk input , textarea , & select alias elemen HTML yang bisa dikasih
atribut disabled .

Listing 3.7: Contoh Checkbox & Radio Binding


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 </head>
7 <body>
8
9 <input type="checkbox"
10 data-bind="checked:activated" value="aktif">Aktif
↪</input>
11 <hr>
12 <input type="radio" name="group1"
13 data-bind="enable:activated,checked:selectedColor"
↪value="merah">Merah</input>
14 <input type="radio" name="group1"
15 data-bind="enable:activated,checked:selectedColor"
↪value="biru" >Biru</input>
16
3.2. FORM INPUT 33

17 <p data-bind="text:selectedColor"></p>
18
19 <script src="knockout-2.2.1.debug.js"></script>
20 <script>
21 function VM(){
22 var self = this;
23
24 self.activated = ko.observable(false);
25 self.selectedColor = ko.observable('');
26
27 };
28
29 var vm = new VM();
30 ko.applyBindings(vm)
31 </script>
32 </body>
33 </html>

Gambar 3.13: Checkbox nggak dicek, radio non-aktif.

Gambar 3.14: Checkbox dicek, radio aktif (bisa diklik)


34 BAB 3. DATA BINDING

Gambar 3.15: Radio dipilih, teks paragraf diupdate

Untuk ngerubah status checkbox & radio, coba ketik kode di bawah ini di konsol.
> vm.activated(false)
> vm.selectedColor('')

3.3 Control-flow Binding

Control-flow binding adalah binding yang bisa ngerubah struktur halaman atau scope
(konteks) dari data-binding.

if & ifnot

Kedua binding ini berfungsi sebagai kondisional untuk rendering elemen html. Ku-
rang lebih mirip dengan visible binding. Bedanya, if & if-not nggak ngerubah properti
visible (css) dari sebuah elemen tapi secara fisik nambahin atau hapus child elemen
yang ada di dalamnya.
Sebagai contoh, kita pake Listing 3.3 & kita modifikasi sedikit.

Listing 3.8: Demo if & if-not


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>if-ifnot</title>
6 </head>
3.3. CONTROL-FLOW BINDING 35

7 <body>
8
9 <h1>Miami Heat</h1>
10 <a href="#" data-bind="click:handleClick">
11 <span data-bind="text:linkText"></span>
12 </a>
13
14 <p id="news" data-bind="if:showNews">
15 The White House says President Barack Obama has
↪congratulated the Miami Heat&#39;s
16 head coach on winning the NBA championship the second year
↪ in a row.
17 </p>
18
19 <p id="info" data-bind="ifnot:showNews"
20 style="background-color: burlywood">
21 Klik link di atas
22 </p>
23
24 <script src="knockout-2.2.1.debug.js"></script>
25 <script>
26 function VM(){
27 var self = this;
28 self.showNews = ko.observable(false);
29 self.linkText = ko.computed(function(){
30 return self.showNews() ? 'Hide':'Show';
31 })
32 self.handleClick = function(){
33 self.showNews(!self.showNews());
34 }
35 };
36
37 var vm = new VM();
38 ko.applyBindings(vm)
39 </script>
40 </body>
41 </html>
36 BAB 3. DATA BINDING

Gambar 3.16: Sebelum Show diklik (atas) & sesudah

Sebelum Show diklik, struktur p#news adalah seperti berikut. Kosong, nggak ada
teksnya.
<p id="info" data-bind="if:showNews"></p>
Setelah Show diklik, strukturnya berubah jadi di bawah ini. Kalo Hide diklik, teksnya
akan dihapus lagi.
<p id="info" data-bind="if:showNews">
The White House says President Barack Obama ... dst
</p>
Untuk p#info adalah kebalikannya, karena elemen ini pake binding ifnot . Kalo
Show diklik, teks elemen ini dihapus. Kalo Hide diklik, teksnya ada lagi.
3.3. CONTROL-FLOW BINDING 37

foreach

Foreach binding kita pake untuk nampilin beberapa elemen sekaligus.

Listing 3.9: Contoh Foreach


1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>foreach</title>
6 </head>
7 <body>
8
9 <select data-bind="value:elementCount">
10 <option value="1">1</option>
11 <option value="2">2</option>
12 <option value="3">3</option>
13 </select>
14
15 <ul data-bind="foreach:elements">
16 <li data-bind="text:$data"></li>
17 </ul>
18
19 <script src="knockout-2.2.1.debug.js"></script>
20 <script>
21 function VM(){
22 var self = this;
23
24 self.elements = ko.observableArray([])
25
26 self.elementCount = ko.observable(0);
27 self.elementCount.subscribe(function(newValue){
28 var val = parseInt(newValue);
29
30 //kalo sama, nggak usah diterusin
31 if(self.elements.length === val) return;
32
33 var remove = !!(self.elements().length > val);
34 while(self.elements().length !== val){
35 if(remove){
38 BAB 3. DATA BINDING

36 self.elements().pop();
37 }else{
38 var n = Math.round(Math.random() * 10);
39 self.elements().push(n);
40 }
41 }
42 self.elements.valueHasMutated();
43 })
44 };
45
46 var vm = new VM();
47 ko.applyBindings(vm)
48 </script>
49 </body>
50 </html>

Gambar 3.17: Foreach binding tampilin 1, 2,& 3 elemen

Baris 15 - 17 dalam Listing 3.9 berarti "bikin li untuk setiap data/objek dalam elements
untuk nampilin $data ". Perhatiin tanda dolar ( $ ) didepan kata 'data'. $data adalah
referensi/pointer ke objek dalam elements yang sedang diproses.

with

With binding kita pake untuk ngatur scope (konteks) dari data-binding sebuah elemen.
Listing 3.6 bisa kita sederhanain lagi pake with seperti contoh berikut. Kita nggak
perlu pake observable selectedCityName & selectedCityPopulation karena kita
pake with .
3.3. CONTROL-FLOW BINDING 39

Listing 3.10: Contoh With-Binding


1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>With</title>
6 </head>
7 <body>
8
9 <select data-bind="options:data,
10 optionsText:'nama',
11 value:selectedCity,
12 optionsCaption:'Pilih kota'"></select>
13
14 <div data-bind="visible:selectedCity"
15 style="background-color: yellow;padding: 10px">
16
17 <h3>Populasi</h3>
18
19 <p data-bind="with:selectedCity">
20 <span data-bind="text:nama"></span>,
21 <span data-bind="text:populasi"></span>
22 </p>
23
24 </div>
25
26 <script src="knockout-2.2.1.debug.js"></script>
27 <script>
28
29 var populasi = [
30 {nama:'Jakarta',propinsi:'DKI Jakarta',populasi
↪:9607787},
31 {nama:'Surabaya',propinsi:'Jawa Timur',populasi
↪:2765487},
32 {nama:'Bandung',propinsi:'Jawa Barat',populasi:2394873},
33 {nama:'Bekasi',propinsi:'Jawa Barat',populasi:2334871}
34 ];
35
36 function VM($data){
37 var self = this;
40 BAB 3. DATA BINDING

38 self.data = ko.observableArray($data);
39 self.selectedCity = ko.observable();
40 };
41
42 var vm = new VM(populasi);
43 ko.applyBindings(vm);
44 </script>
45 </body>
46 </html>

3.4 Template Binding

Template binding dipake untuk masukin elemen DOM hasil pemrosesan sebuah tem-
plate secara dinamis. Ada dua macam template yang disuport oleh KO, yaitu:
• Native template, seperti yang dipake control-flow binding.
• String-based template yang memungkinkan kita pake library lain misalnya jquery
template, handlebars, dan lain-lain.

Listing 3.11: Contoh Template-Binding


1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8"/>
5 <title>Template</title>
6 </head>
7 <body>
8
9 <input type="radio" name="menu" value="master"
10 data-bind="checked:template">Master</input>
11
12 <input type="radio" name="menu" value="detail"
13 data-bind="checked:template">Detail</input>
14
15 <div data-bind="template:{name:template(),
16 data:templateData()}">
3.4. TEMPLATE BINDING 41

17
18 </div>
19
20 <!-- templates -->
21 <script type="text/html" id="master">
22 <div style="background-color:#ccc">
23 <h1 data-bind="text:$data.name"></h1>
24 <p>Race : <span data-bind="text:$data.race"></span></p>
25 <p>Description: <span data-bind="text:$data.desc">
↪</span></p>
26 </div>
27 </script>
28
29 <script type="text/html" id="detail">
30 <div style="background-color:#ffc">
31 <h1>Detail</h1>
32 <table>
33 <tr>
34 <td>Role</td>
35 <td data-bind="text:$data.role"></td>
36 </tr>
37 <tr>
38 <td>Armament</td>
39 <td data-bind="text:$data.armament"></td>
40 </tr>
41 <tr>
42 <td>Protection</td>
43 <td data-bind="text:$data.protection"></td>
44 </tr>
45 <tr>
46 <td>Sight Range</td>
47 <td data-bind="text:$data.sightRange"></td>
48 </tr>
49 </table>
50 </div>
51 </script>
52
53 <script src="knockout-2.2.1.debug.js"></script>
54 <script>
55
56 var data = {
42 BAB 3. DATA BINDING

57 name:'Marauder',
58 race:'Terran',
59 desc:'The marauder is a terran infantry unit in
↪StarCraft II. It replaced the firebat in multiplayer
↪during development.',
60 details:{
61 role:'Heavy assault infantry',
62 armament:'Punisher Grenade Launcher',
63 protection:'5-4 Armored Infantry Suit',
64 sightRange:10
65 }
66 }
67
68 function VM(data){
69
70 var self = this;
71 var _masterData = {
72 name:data.name,
73 race:data.race,
74 desc:data.desc
75 }
76 var _detailData = data.details;
77
78 self.template = ko.observable('master');
79 self.templateData = ko.computed(function(){
80 return (self.template() === 'master') ? _masterData :
↪_detailData;
81 })
82 }
83
84 var vm = new VM(data);
85 ko.applyBindings(vm);
86 </script>
87 </body>
88 </html>
3.4. TEMPLATE BINDING 43

Gambar 3.18: Master & Detail mode

Template dalam Listing 3.11 baris 21-51 disebut embedded template, lawan dari exter-
nal template. Embedded template didefinisikan dalam <script type='text/html'> .
Tujuannya supaya nggak ditampilin sama browser karena browser nggak kenal script
dengan atribut type='text/html' .
©2013 Anggie Bratadinata | masputih.com

Bab 4

Contoh : Shopping Cart

Setelah kita belajar sepotong-sepotong, sekarang kita lihat contoh aplikasi sederhana
pake materi yang udah kita pelajari. Di sini saya bikin shopping cart dibantu Twitter
Bootstrap1 untuk style & layout.

Z Info
Video untuk demo aplikasi ini bisa dilihat di http://youtu.be/awbePbC
3d0g. Aplikasinya bisa dicoba online di http://masputih.com/belaj
ar-ko/shoppingcart/

4.1 Planning

Aplikasi ini butuh tiga komponen utama yaitu Produk/Item, Daftar Produk, & Cart.
Daftar produk tugasnya nampilin produk & interface untuk beli produk. Cart untuk
nampilin produk yg dibeli & interface untuk modifikasi jumlah belanjaan. Karena masing-
masing komponen fungsinya beda, saya bikin tiga VM, satu untuk masing-masing kom-
ponen. Desain awalnya seperti Gambar 4.1.
1
http://twitter.github.io/bootstrap/

45
46 BAB 4. CONTOH : SHOPPING CART

Gambar 4.1: Desain View & VM

Untuk implementasinya, saya pisahin masing-masing VM dalam file/modul .js tersendiri


plus satu file sebagai entry point yang nantinya berfungsi untuk inisialisasi aplikasi.
• itemlist.js
• cart.js
• item.js
• main.js (entry point)
Aplikasi ini nggak pake koneksi ke server, jadi saya nggak butuh VM khusus untuk
Daftar Produk, cukup sebuah observableArray aja. Jadi, itemlist.js saya coret
dari daftar modul sebagai gantinya, saya bikin OA di dalam main.js untuk daftar
item/produk.
4.2. IMPLEMENTASI 47

4.2 Implementasi

Pertama saya bikin dua direktori, js/ untuk file JS aplikasi & vendor/ untuk Boot-
strap & Knockout (Gambar 4.2). Terus bikin file index.html & bikin halaman seperti
Gambar 4.3. Selanjutnya, saya bikin modul JavaScript. Saya hapus sebagian besar
bagian-bagian statis di index.html & saya sisakan secukupnya untuk template.

Gambar 4.2: Direktori Aplikasi

Gambar 4.3: Shopping Cart


48 BAB 4. CONTOH : SHOPPING CART

Kode lengkapnya adalah seperti di bawah ini. Baca komentar di dalamnya untuk pen-
jelasan kode.

Listing 4.1: index.html


1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title>KO Cart</title>
6 <link href="vendor/bootstrap/css/bootstrap.min.css" rel="
↪stylesheet" media="screen">
7 </head>
8 <body>
9
10 <div class="container">
11 <div class="row-fluid">
12
13 <div class="span7">
14 <h4><i class="icon-list"></i> Produk</h4>
15 <hr>
16 <div data-bind="foreach:items">
17 <div class="well">
18 <div class="row-fluid">
19 <div class="span8">
20 <div data-bind="text:name"></div>
21 <div>Stok:
22 <span data-bind="text:stock"></span>
23 </div>
24 </div>
25 <div class="span3">
26 @<span data-bind="text:price"></span>
27 </div>
28 <div class="span1">
29 <button class="btn btn-success btn-small"
30 data-bind="visible:inStock,
31 click:$parent.buy">
32 Beli
33 </button>
34 <span class="label label-important"
35 data-bind="visible:!inStock()">
4.2. IMPLEMENTASI 49

36 Habis
37 </span>
38 </div>
39
40 </div>
41 </div>
42 </div>
43
44 </div>
45
46 <div class="span5">
47 <div class="well" style="background-color: #fff" data-
↪bind="with:cart">
48 <h4> <i class="icon-shopping-cart"></i> Cart</h4>
49 <div data-bind="if:isEmpty">
50 <hr>
51 Kosong.
52 </div>
53 <div data-bind="ifnot:isEmpty">
54 <table class="table" >
55 <thead>
56 <th style="width:15em">Item</th>
57 <th>Jml</th>
58 <th style="width:6em">Subtotal</th>
59 <th></th>
60 </thead>
61 <tbody data-bind="foreach:items">
62 <tr>
63 <td>
64 <span data-bind="text:name"></span>
65 @Rp <span data-bind="text:price"></span>
66 </td>
67 <td>
68 <input type="text"
69 class="input-mini"
70 style="width:30px"
71 data-bind="value:bought"/>
72 </td>
73 <td>Rp
74 <span data-bind="text:subtotal">
75 </span>
50 BAB 4. CONTOH : SHOPPING CART

76 </td>
77 <td>
78 <button class="btn btn-mini"
79 data-bind="click:reset">
80 <i class="icon-trash"></i>
81 </button>
82 </td>
83 </tr>
84 </tbody>
85 <tfoot>
86 <tr style="background-color:#a7cf1d;font-weight:
↪ bold">
87 <td colspan="2" style="text-align: right">
↪Total</td>
88 <td colspan="2">Rp
89 <span data-bind="text:total"></span>
90 </td>
91 </tr>
92 </tfoot>
93 </table>
94 </div>
95
96 </div>
97 </div>
98 </div>
99 </div>
100
101 <script src="vendor/knockout-2.2.1.debug.js"></script>
102 <script src="js/main.js"></script>
103 <script src="js/cart.js"></script>
104 <script src="js/item.js"></script>
105 <script>
106 var items = [
107 {id:0,name:'Sabun',price:'10000',stock:10},
108 {id:1,name:'Minyak',price:'30000',stock:5},
109 {id:2,name:'Kopi',price:'40000',stock:15},
110 {id:3,name:'Gula',price:'15000',stock:20},
111 {id:3,name:'Susu',price:'15000',stock:0}
112 ]
113
114 var app = new shoppingCart.App(items);
4.2. IMPLEMENTASI 51

115 app.init(items);
116 ko.applyBindings(app);
117 </script>
118 </body>
119 </html>

Listing 4.2: cart.js


1 //namespace
2 var shoppingCart = shoppingCart || {};
3
4 shoppingCart.Cart = function(){
5 var self = this;
6
7 /**
8 * Daftar item yg udah dibeli
9 */
10 self.items = ko.observableArray([]);
11
12 /**
13 * Cart kosong (true) atau nggak (false)
14 */
15 self.isEmpty = ko.computed(function(){
16 return (self.items().length === 0);
17 });
18
19 /**
20 * Tambahin item ke daftar item yg dibeli
21 * @param item
22 */
23 self.add = function(item){
24 //cari item yg id nya sama
25 //di daftar item yg udah dibeli
26 var it = ko.utils.arrayFirst(self.items(),function(obj){
27 return (obj.id === item.id);
28 });
29
30 //kalo item belum ada di
31 //daftar item yg di beli
32 if(it === null){
52 BAB 4. CONTOH : SHOPPING CART

33 //tambahin ke daftar item


34 self.items.push(item);
35
36 //deteksi jumlah yg dibeli
37 //kalo jumlahnya 0,
38 //hapus dari daftar item
39 item.bought.subscribe(function(newValue){
40 if(parseInt(newValue) === 0){
41 self.items.remove(item);
42 }
43 });
44 }
45 };
46
47 /**
48 * Total belanja
49 */
50 self.total = ko.computed(function(){
51 var total = 0;
52 ko.utils.arrayForEach(self.items(),function(item){
53 if(item.bought()){
54 total += item.subtotal();
55 }
56 });
57 return total;
58 });
59 };

Listing 4.3: item.js


1 //namespace
2 var shoppingCart = shoppingCart || {};
3
4 shoppingCart.Item = function(data){
5 var self = this;
6 self.id = data.id;
7 self.name = data.name;
8 self.price = data.price;
9
10 /**
4.2. IMPLEMENTASI 53

11 * Nilai stok awal


12 * @private
13 */
14 var _originalStock = data.stock;
15
16 /**
17 * Stok yg tersisa
18 */
19 self.stock = ko.observable(data.stock);
20
21 /**
22 * Jumlah yg udah dibeli
23 */
24 self.bought = ko.observable(0);
25
26 /**
27 * Deteksi perubahan jumlah yg dibeli
28 * utk update sisa stok
29 */
30 self.bought.subscribe(function(newValue){
31
32 //newValue bertipe string kalo
33 //diubah pake text input, perlu
34 //dijadiin integer dulu
35 var val = parseInt(newValue);
36
37 //kalo val lebih besar dari stok awal,
38 //samain dgn stok awal, jadi
39 //jml maks yg bisa dibeli sama
40 //dgn stok awal
41 if(val > _originalStock){
42 val = _originalStock;
43 self.bought(val);
44 return;
45 }
46 self.stock(_originalStock - val);
47 });
48
49 /**
50 * Naekin jumlah yg dibeli
51 */
54 BAB 4. CONTOH : SHOPPING CART

52 self.buy = function(){
53 //self.bought() bertipe string kalo
54 //diubah pake text input
55 //jadi perlu dijadiin integer dulu
56 self.bought(parseInt(self.bought())+1);
57 };
58
59 /**
60 * Batalin pembelian item.
61 */
62 self.reset = function(){
63 self.bought(0);
64 };
65
66 /**
67 * Ada stok (true) atau kosong (false)
68 */
69 self.inStock = ko.computed(function(){
70 return (self.stock() > 0);
71 });
72
73 /**
74 * Subtotal untuk item ini
75 */
76 self.subtotal = ko.computed(function(){
77 return self.bought() * self.price;
78 });
79 };

Listing 4.4: main.js


1 //namespace
2 var shoppingCart = shoppingCart || {};
3
4 shoppingCart.App = function(){
5 var self = this;
6 self.items = ko.observableArray([]);
7 self.cart = new shoppingCart.Cart();
8
9 self.buy = function(item){
4.2. IMPLEMENTASI 55

10 //tambahin item ke cart


11 self.cart.add(item);
12 //update jumlah yg dibeli
13 item.buy();
14 };
15
16 self.init = function(items){
17
18 for(var i = 0,len=items.length;i<len;i++){
19 var item = new shoppingCart.Item(items[i]);
20 self.items().push(item);
21 }
22 };
23 };
©2013 Anggie Bratadinata | masputih.com

Bab 5

Penutup

Buku ini memang nggak mencakup semua fitur & pembahasannya juga nggak terlalu
detil, tapi saya rasa udah cukup untuk pemula yang ingin pake KO. Kalo Anda paham
JavaScript, KO relatif gampang dipelajari. Kalo belum paham JavaScript, silakan baca
ebook saya yang berjudul Mengenal JavaScript 1 .
Untuk bikin aplikasi yang serius, saya sarankan Anda baca & pelajari materi lanjutan
seperti:
• Writeable Computed Observable
• Elemen Virtual
• Custom Binding
• Template eksternal
Happy coding! ,

1
http://masputih.com/2013/01/ebook-gratis-mengenal-javascript

57
©2013 Anggie Bratadinata | masputih.com

Referensi

Berikut ini beberapa situs menarik untuk belajar KnockoutJS.


• http://learn.knockoutjs.com
• http://www.knockmeout.net
• https://groups.google.com/forum/#!forum/knockoutjs
• http://www.syncfusion.com/resources/techportal/ebooks/knockoutjs
• http://todomvc.com/architecture-examples/knockoutjs/
• http://www.adobe.com/devnet/html5/articles/getting-started-with-knockoutjs.
html
• http://www.youtube.com/results?search_query=knockoutjs

59
©2013 Anggie Bratadinata | masputih.com

Indeks

checkbox, 34 manual subscription, 12


computed observable, 10, 14 MVC, 3
Control-flow, 34 MVVM, 2
foreach, 37 Model, 3
if & ifnot, 34 View, 3
template, 40 ViewModel, 3, 5, 9
with, 38
notifikasi manual, 15
Data binding, 17
Objek Literal, 5
checked binding, 32
Observable Array, 13
click binding, 17
observer, 9
css binding, 24
disable binding, 32 radio, 34
enable binding, 32
style binding, 24 select, 32
text binding, 20 subscriber, 9, 14
value binding, 27 textarea, 32
valueUpdate, 29 Twitter Bootstrap, 47
visible binding, 23
valueHasMutated, 15
embedded template, 43

input, 32

ko.applyBindings, 6
ko.observable, 9, 12
ko.observableArray, 13, 15

60
©2013 Anggie Bratadinata | masputih.com

TeX

Buku ini ditulis dengan LaTeX dan TeXStudio, bukan MS Word atau sejenisnya. TeX
adalah software untuk typesetting yang tersedia untuk Windows, Linux, dan Mac. Ada
banyak varian TeX, salah satunya LaTeX. Kalau Anda ingin tahu apa itu LaTeX & gi-
mana nulis buku dengan LaTeX jauh lebih cepat daripada pake MS Word, silakan mam-
pir di situs-situs berikut:
• http://en.wikibooks.org/wiki/LaTeX
• http://latex-project.org/guides/
• http://tex.stackexchange.com
• http://texcatalogue.sarovar.org/

TeX Editor (Gratis)

• http://www.xm1math.net/texmaker/
• http://texstudio.sourceforge.net/
• http://www.latexeditor.org/
• http://www.texniccenter.org/
Sekali Anda bisa pake TeX, saya yakin Anda nggak tertarik pake MS Word lagi ,.
Nulis buku/artikel teknikal, terutama tentang pemrograman jauh lebih gampang pake
TeX daripada pake Word. Lebih mirip nulis artikel di blog. Source code eksternal bisa
di-link ke tulisan, nggak perlu kopipas. Kalo source code berubah, cukup recompile
dokumen aja.

61
62 INDEKS

Anda mungkin juga menyukai