AdityaDees: web development

Hot

https://publishers.chitika.com/

Contact us for advertising.
Showing posts with label web development. Show all posts
Showing posts with label web development. Show all posts

28 March 2020

Goodbye jQuery...

14:06 0


As the web standards becoming more mature each day, my prediction is that the need for third-party JavaScript library such as jQuery will slowly decline. jQuery is indeed still one of the best client-side JavaScript library in my opinion and even I still use it on some of my projects, but as the web application becoming more complex, programmers will starting to look at browser's native solution which will (maybe) offers better performance than the third-party library. In this post i will show you some of the browser's native API for replacing jQuery's DOM selector method, the obvious "$" or "jQuery" function. Under the hood, jQuery is actually using Sizzle library for its DOM selector, which i believe (even though I haven't dig inside the source code) Sizzle also using some of the browser's native API.

DOM selector with document.querySelector(selectors)


As the name already suggests, this method under the Document object fetch the first element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned. One important thing that we need to know here is that, using this method will return "null" value when no matches were found. For those who familiar with jQuery need to pay attention as the jQuery selector always returns empty Array when no matches were found. Below I show you some example.


<!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div>This is the first DIV</div>
<div>This is the second DIV</div>
<div>This is the third DIV</div>
<div>This is the fourth DIV</div>
<div>This is the fifth DIV</div>
<script>
// get the first DIV
let firstDiv = document.querySelector('div');
console.log('This is ', firstDiv);

// get the second DIV
let secondDiv = document.querySelector('div:nth-of-type(2)');
console.log('This is the ', secondDiv);
// change the text color to blue
secondDiv.style.color = 'blue';

// get the third DIV
let thirdDiv = document.querySelector('div:nth-of-type(3)');
console.log('This is the ', thirdDiv);
// change the text format to bold
thirdDiv.style.fontWeight = 'bold';

// check if element exists
let sixthDiv = document.querySelector('div:nth-of-type(6)');
if (sixthDiv == null) {
// add the sixth div if it is not exists yet
let newDiv = document.createElement("div")
newDiv.innerText = 'This is the sixth DIV';
document.body.append(newDiv);
}
</script>
</body>
</html>


Tree traversal


querySelector method accepts all type of CSS selector and can be used to do DOM element tree traversal. In fact I already showed one of it the first example using nth-of-type(n) modifier. You can of course use parent children relationship selector also in this case.


<!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div id="parent">
<div class="child">
<div class="grandchild">
<div class="great_grandchild"></div>
</div>
</div>
<div class="child">
<div class="grandchild"></div>
</div>
</div>
<script>
/* TREE TRAVERSAL */
// get the first direct child under parent
let firstChild = document.querySelector('#parent > .child');
console.log('This is the ', firstChild);

// get the great grandchild under parent
let greatGrandChild = document.querySelector('#parent .great_grandchild');
console.log('This is the ', greatGrandChild);

// alternative syntax to get the great grandchild
greatGrandChild = firstChild.querySelector('.great_grandchild');
console.log('This is the ', greatGrandChild);

// add new first child under parent
let newFirstChild = document.createElement("div");
newFirstChild.innerText = 'The real 1st child';
document.querySelector('#parent').prepend(newFirstChild);

// get the parent of great grandchild
let parentOfGrandChild = greatGrandChild.parentNode;
console.log(parentOfGrandChild);
</script>
</body>
</html>


Multiple DOM element matches and manipulation with querySelectorAll


The querySelectorAll method behaves almost similar with the querySelector, except that it returns not only single match but an array in form of NodeList object instead. You can use this if you want to manipulate more than one element that match with your specified selector. Just remember to add :scope pseudo class at the very first of selector string to make sure the browser only get the child element under the specified element.


<!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<ul id="bio">
<li class="name">The first one</li>
<li class="location">Tsukuba, Japan</li>

<li class="name">The second one</li>
<li class="location">Tokyo, Japan</li>

<li class="name">The third one</li>
<li class="location">Jakarta, Indonesia</li>

<li class="name">The fourth one</li>
<li class="location">Seoul, South Korea</li>

<li class="name">The fifth one</li>
<li class="location">Wuhan, China</li>
</ul>
<script>
/* querySelectorAll */
// get all names
let names = document.querySelectorAll(':scope #bio .name');
console.log('Number of names ', names.length);
console.log('The elements are ', names);

// get all locations
let locations = document.querySelectorAll(':scope #bio .location');
console.log('The elements are ', locations);

// make all location texts italic
locations.forEach(e => e.style.fontStyle = 'italic');

// prepend "name" text inside name element
names.forEach(e => e.prepend('Name: '));

// add empty list element with bottom border after location
// as a data separator
locations.forEach(function(e){
let borderedList = document.createElement('li');
borderedList.style.borderBottom = '1px solid #999';
e.after(borderedList);
});
</script>
</body>
</html>


Pretty neat huh? :D


Sibling manipulation with previousElementSibling and nextElementSibling


It is very often we want to manipulate DOM elements which are positioned on the same level as current selected element, or the siblings of current element. In this case we can use the previousElementSibling and nextElementSibling property.


<!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div id="friends">
<div class="friend">Harada</div>
<div class="friend">Sasaki</div>
<div class="friend">Iqbal</div>
<div class="friend">Michael</div>
<div class="friend">Megumi</div>
</div>
<script>
/* SIBLINGS */
// get iqbal
let iqbal = document.querySelector('#friends .friend:nth-of-type(3)');
console.log(iqbal);

// who is our friend before iqbal
let beforeIqbal = iqbal.previousElementSibling;
// change the color to orange
beforeIqbal.style.color = 'orange';

// who is our friend after iqbal
let afterIqbal = iqbal.nextElementSibling;
// change the color to purple
afterIqbal.style.color = 'purple';</script>
</body>
</html>
Read More

17 January 2019

Operasi Array dan Object dengan Plain Vanilla Javascript

16:59 0


Dengan semakin matangnya standar JavaScript saat ini berkat hadirnya edisi ke-enam dari standar ECMAScript 2015 dan dukungan berbagai browser modern, pemrograman web dengan Javascript menjadi semakin mudah. Salah satu operasi pemrograman yang sering saya lakukan adalah operasi yang melibatkan Array dan Object (utamanya JSON). Berikut ini adalah beberapa code snippet yang saya coba dokumentasikan yang mungkin bermanfaat bagi teman-teman yang membaca artikel ini. Karena fungsi-fungsi/metode-metode object yang digunakan dalam artikel ini adalah standar, walaupun snippet yang saya contohkan untuk digunakan pada browser (client-side), maka kemungkinan besar snippet kode-kode ini juga bisa berjalan pada NodeJS a.k.a JavaScript di server-side. Karena artikel ini tidak mencakup dasar-dasar pemrograman Javascript, ada baiknya teman-teman yang belum mengenal JavaScript mempelajari terlebih dahulu dasar-dasar pemrograman JavaScript sebelum membaca artikel ini.



Iterasi Array dengan method forEach


Untuk melakukan iterasi terhadap isi dari Array biasanya kita menggunakan loop construct seperti for, alternatifnya kita bisa juga menggunakan forEach yang relatif lebih praktis.


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// sebuah Array berisi daftar nama teman-teman
var temanTeman = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
temanTeman.forEach(function(teman) {
// tampilkan ke console JavaScript
console.log(teman);
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>


Iterasi Object dengan method forEach


Untuk melakukan iterasi terhadap property dan nilai yang ada dalam sebuah Object kita bisa juga menggunakan forEach dengan cara sedikit berbeda seperti berikut ini:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
var sebuahObject = {nama: 'Ari', pekerjaan: 'Mahasiswa', usia: 36}
Object.keys(sebuahObject).forEach(function(prop) {
// ambil nilai untuk prop ini
const propVar = Object.getOwnPropertyDescriptor(sebuahObject, prop);
// tampilkan pada body dokumen HTML
document.writeln(prop + ': ' + propVar.value + '<br/>');
});
</script>
</body>
</html>


Mencari tahu apakah sebuah nilai ada pada sebuah Array dengan method includes


Untuk mengetahui apakah sebuah nilai ada pada sebuah Array kita bisa menggunakan includes, seperti contoh berikut ini:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// sebuah Array berisi daftar nama teman-teman
var temanTeman = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// apakah "Budi" ada dalam daftar-daftar teman-teman kita?
const yangKitaCari = 'Budi'
if (temanTeman.includes(yangKitaCari)) {
// tampilkan ke console JavaScript
console.log(yangKitaCari+' ada dalam daftar!');
// tampilkan pada body dokumen HTML
document.writeln('<p>'+yangKitaCari+' ada dalam daftar!</p>')
} else {
// tampilkan ke console JavaScript
console.log(yangKitaCari+' TIDAK ADA dalam daftar!');
// tampilkan pada body dokumen HTML
document.writeln('<p>'+yangKitaCari+' TIDAK ADA dalam daftar!</p>')
}
</script>
</body>
</html>


Menggabungkan dua atau lebih Array menjadi satu dengan method concat


Kita bisa dengan mudah menggabungkan dua atau lebih Array menjadi satu dengan menggunakan concat, seperti contoh berikut ini:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// menggabungkan dua atau lebih Array menjadi satu
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
var temanDia = ['Ferry', 'Giri', 'Helmi', 'Iman'];
// gabungkan Array menjadi Array baru
var temanKudanDia = temanKu.concat(temanDia);
console.log(temanKudanDia);
temanKudanDia.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>


Melakukan filter isi Array berdasarkan kriteria tertentu dengan method filter


Untuk melakukan filter terhadap isi dari Array kita bisa menggunakan filter. Callback dari method filter harus mengembalikan nilai true apabila elemen tersebut ingin dipertahankan dalam Array atau sebaliknya. Bisa dilihat pada contoh berikut ini:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// mem-filter Array sesuai dengan kriteria tertentu
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma', 'Kampret', 'Kecebong'];
var benarBenarTemanKu = temanKu.filter(teman => teman!='Kampret'&&teman!='Kecebong');
console.log(benarBenarTemanKu);
benarBenarTemanKu.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>


Mengubah isi Array menjadi Array baru dengan isi yang sudah dimodifikasi dengan method map


Ada kalanya kita ingin memodifikasi/mengubah isi sebuah Array. Hal tersebut bisa dilakukan dengan mudah dengan map:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat Array baru yang isi merupakan hasil modifikasi dari isi Array sebelumnya
var stringTemanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// stringTemanKu sebelumnya adalah Array berisi string
// sekarang kita ubah menjadi Array baru berisi object
var objectTemanKu = stringTemanKu.map(teman => {
var objectTeman = {nama: teman, status: 'teman'};
return objectTeman;
});
console.log(objectTemanKu);
// bisa juga sebaliknya, dari Array berisi object menjadi Array berisi string
var stringTemanKuJuga = objectTemanKu.map(teman => teman.nama+' adalah seorang '+teman.status);
console.log(stringTemanKuJuga);
stringTemanKuJuga.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>


Mengubah string menjadi Array elemennya adalah setiap huruf dari string tersebut dengan function Array.from


Bagaimana apabila kita ingin mengubah sebuah string dan memecahnya menjadi Array yang berisikan setiap huruf dari string tersebut? Mudah!:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat Array dari string
var deretanHuruf = 'ABCDEFGHIJKLM';
var deretanHurufArray = Array.from(deretanHuruf);
deretanHurufArray.forEach(function(huruf) {
// tampilkan pada body dokumen HTML
document.writeln('Ini huruf '+ huruf + '!<br/>');
});
</script>
</body>
</html>


Mengubah Array menjadi string dengan method join


Bagaimana sebaliknya apabila kita ingin mengubah sebuah Array menjadi sebuah string? Mudah!:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat string dari Array
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// kita persatukan teman-teman kita dengan sebuah koma
var stringTemanKu = temanKu.join(', ');
// tampilkan pada body dokumen HTML
document.writeln('Teman-temanku adalah: '+ stringTemanKu);
</script>
</body>
</html>


Melakukan tes pada setiap isi Array apakah sudah memenuhi kriteria dengan method every


Adakalanya kita ingin mengetahui apakah setiap anggota dari Array sudah memenuhi kriteria tertentu, untuk melakukan tes tersebut kita bisa menggunakan every:


<!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// melakukan tes pada setiap elemen Array apakah memenuhi kriteria tertentu
var anggota = [
{nama: 'Asri', usia: 17},
{nama: 'Budi', usia: 18},
{nama: 'Choirul', usia: 19},
{nama: 'Deni', usia: 20},
{nama: 'Erma', usia: 15}
];
// apakah semua orang dalam anggota sudah lebih dari 16 tahun?
var semuaSudahDewasa = anggota.every(orang => orang.usia>16);
if (semuaSudahDewasa) {
document.writeln('Semua sudah dewasa!');
} else {
document.writeln('Masih ada di antara mereka yang belum dewasa!');
}
</script>
</body>
</html>


Semoga artikel ini bermanfaat, apabila ada pertanyaan terkait dengan beberapa fungsi dasar dari JavaScript bisa teman-teman tanyakan pada kolom komentar.

Read More

08 February 2018

Membuat Aplikasi Berbasis Web "Single Page Application" dengan Vue.js (Bagian 1)

20:15 0

Javascript saat ini semakin populer digunakan dalam pengembangan aplikasi berbasis web baik di sisi client (browser) maupun server, yang semakin diperkuat dengan munculnya standar-standar ECMAScript terbaru seperti ECMAScript6 (ES6) atau biasa disebut juga ECMAScript 2015 (ES2015). Untuk lebih lengkapnya mengenai ES6 ini silahkan baca halaman web penjelasan dari Luke Hoban yang sangat bermanfaat ini. Sejarahnya dulu saya ingat Javascript ini adalah bahasa pemrograman client-side yang paling menyebalkan karena perbedaan standar setiap browser, aplikasi web kita berjalan lancar di Interner Explorer 5 atau 6, pas dijalankan dengan Mozilla, Netscape atau Firefox tidak jalan sama sekali dan juga berlaku sebaliknya, Mikocok ehhh maksud saya Microsoft cenderung membuat implementasi mereka sendiri. Seiring dengan semakin maraknya penggunaan aplikasi berbasis web, Javascript semakin banyak digunakan untuk membuat aplikasi web yang responsif dan "reaktif". Istilah "Reaktif" sedang "in" dalam pengembangan web saat ini, yang merujuk kepada kemampuan untuk "mereaktifkan" elemen DOM (Document Object Model)/tag HTML sehingga ketika diubah nilainya pada kode Javascript, maka secara otomatis tag HTML tersebut juga akan berubah, begitu juga sebaliknya apabila kita melalukan perubahan di sisi HTML, maka perubahan tersebut akan terefleksi pada kode Javascript. Beberapa framework/library Javascript yang memungkinkan kita membangun aplikasi web yang reaktif ini antara lain: AngularJS (bukan Angular), Backbone.js, Ember, React, Riot, Polymer, dan yang akan kita bahas kali ini adalah Vue.js yang menyatakan dirinya sebagai "The Progressive JavaScript Framework" (kayanya semua framework menyatakan diri mereka paling hebat dibandingkan dengan framework lain 😬).



Reaktifitas


Untuk melihat contoh "reaktifitas" dengan Vue, silahkan buat sebuah file HTML bernama index.html dan masukkan kode berikut:

index.html


<!doctype html>
<html lang="id">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<title>Contoh Reaktifitas</title>
</head>
<body>
<div id="spa">
<div class="jumbotron jumbotron-fluid p-3">
<h1 class="display-4 text-center">{{ teks_yang_reaktif?teks_yang_reaktif:'Hmmmm...' }}</h1>
<hr class="my-4"/>
<p class="lead text-center"><input type="text" class="form-control" v-model="teks_yang_reaktif"/></p>
</div>
<script>
var spa = new Vue({
el: '#spa',
data: {
teks_yang_reaktif: 'Sebuah Teks yang Reaktif!'
}
})
</script>
</body>
</html>



Buka file index.html ini pada browser dan kita akan melihat seperti berikut ini:




Single Page Application


Dengan munculnya library/framework reaktif seperti Vue.js ini mendorong model pengembangan aplikasi berbasis web "Single Page Application (SPA)", dimana semua "view" atau tampilan antar muka dibangun dengan hanya menggunakan sebuah file HTML yang kemudian akan me-load view komponen/modul lain dengan meng-injeksi (atau istilah kerennya: render) secara dinamis dengan Javascript. Dengan model SPA ini maka aplikasi di sisi server tidak lagi harus mengirimkan respon balik halaman HTML full, cukup data saja dalam format JSON (menggunakan AJAX) misalnya yang kemudian akan direaktifkan oleh Vue, setiap perubahan di sisi klien akan memicu perubahan pada server, begitu juga sebaliknya dan pada akhirnya komunikasi data antara client dengan server berlangsung lebih cepat karena ukuran data yang kecil. Kita lihat contoh sederhana dengan menggunakan Vue berikut ini:



index.html


<!doctype html>
<html lang="id">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<script src="assets/js/vue-router.min.js"></script>
<title>Single Page Application Vue.js</title>
</head>
<body>
<div id="spa"><!-- elemen root/utama dari SPA Vue -->
<!-- Navigasi utama aplikasi SPA
perhatikan tag "router-link" adalah tag khusus untuk membuat hyperlink ke router Vue -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">SPA Vue.js</router-link>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navigasi"
aria-controls="navigasi" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navigasi">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" to="/">Home</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" to="/berita">Berita</router-link>
</li>
</ul>
</div>
</nav>

<!-- link dari "router-link" di atas akan merender view masing2 di dalam tag "router-view" -->
<div id="main-content">
<router-view></router-view>
</div>
</div>

<!-- template view untuk komponen "Home" -->
<script type="text/x-template" id="home">
<div class="jumbotron jumbotron-fluid"><h1 class="display-4 text-center">{{ judul }}</h1>
<hr class="my-4"/>
<p class="lead text-center">{{ konten }}</p>
</script>

<!-- template view untuk komponen "Berita" -->
<script type="text/x-template" id="berita">
<div>
<p class="p-1"><input type="text" class="form-control" v-model="keywords"
v-on:keyup="search"
placeholder="Masukkan kata kunci pencarian"></p>
<div v-if="berita_filtered.length>0">
<div class="berita p-2" v-for="b in berita_filtered">
<p class="h4">{{ b.judul }}</p>
<p class="lead">{{ b.konten }}</p>
<hr/>
</div>
</div>
<div v-else>
<div class="berita p-2" v-for="b in berita">
<p class="h4">{{ b.judul }}</p>
<p class="lead">{{ b.konten }}</p>
<hr/>
</div>
</div>
</div>
</script>

<!-- kode javascript untuk menjalankan Vue.js -->
<script src="assets/js/app.js"></script>
</body>
</html>


assets/js/app.js


// 1. Definisikan komponen Vue
// Komponen "Home" akan menampilkan halaman depan aplikasi
const Home = Vue.extend({
template: '#home',
data: function() {
return {
judul: 'Selamat datang di Single Page Application',
konten: 'Vue.js memungkinkan developer web membangun aplikasi web yang dinamis, ringan dan cepat.'
}
}
});
// Komponen "Berita" akan menampilkan daftar berita
var data_berita = {
keywords: '',
berita: [
{judul: 'Lorem Ipsum', konten: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur feugiat, eros quis semper dignissim, libero erat semper ante, non porttitor sem metus a neque.'},
{judul: 'In Vehicula Vulputate', konten: 'In vehicula vulputate eros vitae porttitor. Praesent commodo accumsan semper. Proin eu tellus purus, eu malesuada sapien.'},
{judul: 'Aliquam Laoreet Gravida Erat', konten: 'Aliquam laoreet gravida erat, in hendrerit arcu lobortis id. Cras libero augue, aliquam nec sollicitudin id, molestie eu ante.'},
{judul: 'Donec Adipiscing', konten: 'Donec adipiscing, diam eget tempor volutpat, odio justo molestie dolor, vitae sodales felis risus a mi.'},
{judul: 'Praesent Mollis', konten: 'Praesent mollis placerat mi ut accumsan. Vivamus ultricies lobortis risus, quis venenatis ligula elementum id.'},
],
berita_filtered: []
};
const Berita = Vue.extend({
template: '#berita',
data: function() {
return data_berita;
},
methods: {
search: function() {
var katakunci = new RegExp(this.keywords, 'ig');
if (this.keywords.length > 2) {
this.berita_filtered = this.berita.filter(el => el.judul.search(katakunci)>-1);
} else {
this.berita_filtered = [];
}
}
}
});

// 2. Definisikan routing menuju komponen
const routes = [
{ path: '/', component: Home},
{ path: '/berita', component: Berita }
]

// 3. Buat instance Router Vue
const router = new VueRouter({ routes })

// 4. Tempelkan instance "router" ke App Vue
const spa = new Vue({ router }).$mount('#spa');


Saya akan coba jelaskan beberapa poin penting yang perlu kita perhatikan disini, terutama bagi teman-teman yang baru mengenal Vue:


  1. Untuk contoh SPA ini saya menggunakan juga framework Bootstrap versi 4.0, jadi pastikan bahwa Anda juga sudah mengunduh dan menginstall Bootstrap. Pada tulisan ini semua file CSS saya letakkan pada direktori assets/css/ dan semua file Javascript saya letakkan pada direktori assets/js/;

  2. Untuk menggunakan Vue, kita harus sudah meng-include library Javascript Vue pada bagian head file HTML. Karena kita membangun antar muka SPA, maka kita juga memerlukan Vue Router yang bertugas melakukan routing komponen ke view-nya masing-masing. Unduh library Vue.js di sini dan Vue Router di sini. Atau apabila Anda adalah tipe pemalas download library Javascript gunakan versi CDN masing-masing hehehe;

  3. Perhatikan terdapat custom tag <router-link class="nav-link" to="/">Home</router-link> yang secara otomatis akan dikenali oleh Vue Router dan akan diubah ke tag A sebagai hyperlink menuju route yang ditunjuk oleh atribut "to". Semua hyperlink yang menuju ke route Vue harus menggunakan custom tag ini;

  4. Custom tag <router-view></router-view> berfungsi sebagai tempat penampung (placeholder) dari view untuk masing-masing komponen route;

  5. View atau tampilan untuk masing-masing komponen kita definisikan dengan menggunakan tag <script type="text/x-template" id="berita">. X-Templates adalah salah satu jenis template yang didukung oleh Vue, dan menurut saya yang paling aman dan mudah untuk digunakan untuk kebutuhan aplikasi skala kecil hingga menengah;

  6. Kode dalam bentuk seperti {{ judul }}, {{ konten }} disebut juga sebagai Mustache yang merupakan placeholder untuk data.
    moustache akan otomatis digantikan oleh Vue dengan data yang kita tetapkan pada komponen dan data tersebut sudah bersifat reaktif.

  7. Vue juga memiliki atribut directive, yang kita gunakan pada contoh ini antara lain adalah v-bind, v-if, v-else, v-for, v-model dan v-on. v-model kita gunakan untuk mereaktifkan sebuah tag HTML dengan model data yang kita definisikan pada Vue/komponen, v-if dan v-else memungkinkan kita me-load bagian dari view dengan kondisi tertentu, v-for memungkinkan kita untuk melakukan pengulangan/loop pada view dan sangat berguna untuk menampilkan data dalam bentuk Array atau Object Javascript dan v-on kita gunakan untuk mengaitkan suatu tag HTML dengan "method" yang kita definisikan di dalam kode Javascript Vue;

  8. Semua kode Javascript untuk menjalankan Vue diletakkan pada file assets/js/app.js dan diletakkan pada bagian paling bawah kode HTML;

  9. Variabel objek data_berita pada kode Javascript Vue bersifat static (tidak dinamis), pada aplikasi SPA yang sesungguhnya data berita ini akan diambil melalui AJAX ke database pada aplikasi di sisi server;

  10. Untuk membuat komponen (dalam terminologi aplikasi web MVC tradisional kita bisa anggap komponen merupakan sebuah controller sekaligus model), kita menggunakan sintak Vue.extend({});

  11. Setiap komponen merupakan objek Javascript yang biasanya memiliki property template, data, methods dan/atau computed;

  12. Aplikasi Vue dijalankan dengan membuat instance melalui konstruktor Vue yaitu const spa = new Vue({}). Setelah itu objek spa bisa diakses oleh komponen melalui methods.




Apabila file index.html kita jalankan melalui browser maka kita akan melihat aplikasi kita seperti berikut ini:




Kita bisa lihat bahwa perpindahan antara satu halaman ke halaman lain dilakukan dengan sangat cepat karena tidak membutuhkan request HTTP kembali ke server. Semua proses pengolahan/rendering tampilan antar muka dilakukan di sisi client oleh Vue, request HTTP hanya dibutuhkan untuk komunikasi data dalam format JSON atau plain-text lainnya, bukan untuk kode HTML yang membuat aplikasi menjadi lebih cepat layaknya aplikasi desktop. Pada tulisan bagian 2 kita akan melihat contoh yang sedikit lebih kompleks dengan melibatkan form isian data. Selamat mencoba!

Read More

01 January 2018

Promise : Sebuah Janji Eksekusi dari Javascript

22:31 0


Judul artikel ini mungkin agak sedikit bombastis: "Promise : Sebuah Janji Eksekusi dari Javascript". Promise adalah sebuah mekanisme dari standar ECMAScript 2015 yang memungkinkan kita melakukan eksekusi kode fungsi Javascript asynchronous (salah satunya adalah request AJAX) dan mendapatkan nilai balik (return value) dari eksekusi kode tersebut tidak secara langsung, melainkan berupa objek "Promise" yang menjanjikan eksekusi di masa yang akan datang! Paham? Tidak? kalau teman-teman pembaca tidak paham itu wajar, saya juga awalnya bingung kenapa pula ini ada fitur di bahasa pemrograman pake "janji-janji" segala!? Mari kita tengok definisi dari Promise yang saya kutip dari dokumentasi Mozilla Developer Network :



A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.


Masih belum mudeng? sama saya juga hahaha🤣🤣🤣! Kalau begitu mari kita lihat contoh kode HTML dan Javascript sebagai berikut sebagai berikut:



promise.html


<!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
var datauser = [];
// fungsi untuk melakukan request AJAX
function getUsers(url) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// isi variabel global datauser dengan hasil dari AJAX
datauser = hasil;
});
}
// fungsi untuk mengubah data JSON ke list HTML
function ubahDataKeHTML(datauser) {
var html = '<ul>';
$.each( datauser, function( key, value ) {
html += '<li>'+value.name+' - '+value.email+'</li>'
});
html += '</ul>';
return html;
}
// panggil fungsi 'getUsers'
getUsers('https://jsonplaceholder.typicode.com/users');
// ubah data dari hasil AJAX ke list HTML
var datauserHTML = ubahDataKeHTML(datauser);
// tampilkan isi variabel ke log
console.log(datauser);
console.log(datauserHTML);
// tampilkan data user
$(document).ready(function() {
$('.container').html(datauserHTML);
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html>


Hasil yang muncul adalah sebagai berikut:





Apa yang terjadi? ternyata tidak sesuai apa yang kita harapkan! tag div kita tidak terisi dengan list data user seperti yang kita mau, dan juga ternyata variabel array datauser tidak terisi dengan data padahal tidak ada yang salah dengan kode ini, semua berjalan dengan baik. saya yakin banyak dari teman-teman web programmer yang pernah mengalami hal ini dan garuk-garuk kepala, lalu browsing cari jawaban di Stackoverflow kan? hehehe :D.

Loh mas ngapain ribet, heeellllooowwww?? ubah aja kode-nya, misalnya lakukan eksekusi fungsi ubahDataKeHTML ke dalam fungsi .done dari objek $.ajax()? atau ngapain juga bikin fungsi-fungsi segala?


Hehehe, silahkan saja dicoba, paling nanti ada saatnya kepentok lagi hehehe 😬😬😬. Kegagalan kode di atas terjadi karena eksekusi kode $.ajax dan .done berjalan secara asynchronous/paralel dan tidak terjadi secara berurutan sehingga variabel global datauser mungkin belum terisi dengan hasil dari request AJAX karena request AJAX belum selesai. Penyebab lain adalah karena Javascript hanya bisa mengakses variabel global satu tingkat di atas cakupan fungsi, dalam hal kode di atas variabel datauser berarti dua tingkat di atas cakupan fungsi .done. Cara yang elegan untuk masalah ini adalah dengan menggunakan Promise yang sudah menjadi standar default sejak spesifikasi ECMAScript 2015 atau serin disingkat ES2015. Berikut adalah kode Javascript yang sudah kita ubah dengan memanfaatkan Promise:



promise1.html


<!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
// fungsi untuk melakukan request AJAX dan mengembalikan objek Promise
function getUsers(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// simpan hasil dari AJAX ke callback 'resolve' dari Promise
// untuk kemudian nanti dipakai oleh fungsi '.then'
resolve(hasil);
});
})
}
// fungsi untuk mengubah data JSON ke list HTML
function ubahDataKeHTML(datauser) {
var html = '<ul>';
$.each( datauser, function( key, value ) {
html += '<li>'+value.name+' - '+value.email+'</li>'
});
html += '</ul>';
return html;
}
// panggil fungsi 'getUsers' dan jalankan fungsi '.then'
// argumen dari fungsi '.then' adalah sebuah callback dengan argumen 'hasil'
// yang berisikan objek JSON hasil AJAX
getUsers('https://jsonplaceholder.typicode.com/users').then(function(hasil) {
console.log(hasil);
console.log('Janji telah dipenuhi!');
var datauserHTML = ubahDataKeHTML(hasil);
// tampilkan data user
$(document).ready(function() {
$('.container').html(datauserHTML);
});
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html>


Dengan kode ini kita akan melihat hasil seperti berikut ini:





Penjelasan sederhana dari kode ini adalah, ketika kita menggunakan Promise, maka kita menggunakan callback resolve untuk menyimpan hasil dari request AJAX kita, yang kemudian hasil ini akan tersedia pada argumen callback fungsi .then untuk selanjutnya diolah dan dijadikan HTML oleh fungsi ubahDataKeHTML.



Chaining


Salah satu kelebihan dari Promise adalah memungkinkan terjadinya chaining atau eksekusi Promise berantai, fitur ini berguna ketika kita ingin melakukan eksekusi kode secara berantai dimana eksekusi kode dilakukan benar-benar setelah eksekusi kode sebelumnya sudah selesai atau terpenuhi, seperti bisa kita lihat pada kode berikut:



promise2.html


<!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
// fungsi untuk melakukan request AJAX dan mengembalikan objek Promise
function getUsers(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// simpan hasil dari AJAX ke callback 'resolve' dari Promise
// untuk kemudian nanti dipakai oleh fungsi '.then'
resolve(hasil);
}).fail(function() {
reject('Error pada request AJAX!');
});
})
}
// fungsi untuk mengubah data JSON ke list dan tabel HTML
function ubahDataKeHTML(datauser) {
console.log('Janji pertama (request AJAX) telah dipenuhi');
var list = '<h3>Data users dalam format list</h3>';
list += '<ul>';
var tabel = '<h3>Data users dalam format tabel</h3>';
tabel += '<table class="table table-bordered">';
$.each( datauser, function( key, value ) {
list += '<li>'+value.name+' - '+value.email+'</li>'
tabel += '<tr><td>'+value.name+'</td><td>'+value.email+'</td></tr>'
});
list += '</ul>';
tabel += '</table>';
return {htmlList: list, htmlTable: tabel};
}
// fungsi untuk menginject HTML ke dalam div .container
function injectHTML(html) {
console.log('Janji kedua (ubah JSON ke HTML) telah dipenuhi');
return $('.container').append(html.htmlList).append(html.htmlTable);
}
// fungsi untuk menampilkan log pada console
function terakhir(objJquery) {
console.log('Janji terakhir (inject HTML ke .container) telah dipenuhi');
console.log('Berikut objek jQuery dari nilai balik callback Janji (Promise) sebelumnya:');
console.log(objJquery);
}

// setiap kali '.then' dipanggil maka akan mengembalikan objek Promise
// dan nilai balik dari callback bisa diakses pada callback berikutnya
// yang bisa kita 'chain' tanpa batas
// fungsi '.catch' menangkap hasil dari callback 'reject' yang apabila terjadi
// maka Promise tidak bisa terpenuhi
getUsers('https://jsonplaceholder.typicode.com/users')
.then(hasil => ubahDataKeHTML(hasil))
.then(html => injectHTML(html))
.then(objJquery => terakhir(objJquery))
.catch(error => {
console.log(error);
$('.container').html('<div class="alert alert-danger">Data users gagal diambil disebabkan oleh : '+error+'</div>');
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html>


Kita akan melihat hasil sebagai berikut untuk kode di atas:





Syntax alternatif untuk chaining Promise menggunakan standar ES2017 adalah dengan menggunakan async/await seperti berikut ini:



promise3.html


<script>
...

// alternatif chaining dengan menggunakan 'async/await'
async function ambilUserDanTampilkan(url) {
try {
let hasil = await getUsers(url);
let html = await ubahDataKeHTML(hasil);
let objJquery = await injectHTML(html);
terakhir(objJquery);
} catch(error) {
console.log(error);
$('.container').html('<div class="alert alert-danger">Data users gagal diambil disebabkan oleh : '+error+'</div>');
}
}
// jalankan fungsi async
ambilUserDanTampilkan('https://jsonplaceholder.typicode.com/users');

</script>


Promise.all


Ada kalanya dalam membangun aplikasi web interaktif dengan Javascript kita ingin suatu kode dieksekusi ketika semua persyaratan (eksekusi kode lain) sudah terpenuhi, tanpa memperdulikan urutan selesai-nya persyaratannya tersebut. Misalnya kita melakukan request AJAX ke banyak sumber yang berbeda dan setelah semua request AJAX selesai kita akan mengeksekusi kode terakhir yang menampilkan kotak alert menandakan bahwa semua request tersebut telah selesai, maka kita bisa menggunakan metode Promise.all dalam hal ini. Mari kita ilustrasikan dengan kode berikut ini:



promise-all.html


<!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>

function autentikasiUser(url, username, password) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 1,5 detik
setTimeout(function(){
resolve("Autentikasi user berhasil!"); console.log('Autentikasi berhasil'); }, 1500);
});
}

function ambilDataBerita(url) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 2,5 detik
setTimeout(function(){
resolve('berita terbaru berhasil diambil'); console.log('Berita berhasil diambil'); }, 2500);
});
}

function ambilDataCuaca(url) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 3,5 detik
setTimeout(function(){
resolve('Data cuaca berhasil diambil'); console.log('Cuaca berhasil diambil'); }, 3500);
});
}

let c = ambilDataCuaca('http://servercuaca.com');
let a = autentikasiUser('http://serverautentikasi.com', 'dicarve', 'rahasia');
let b = ambilDataBerita('http://serverberita.com');

let pAll = Promise.all([c, b, a]).then(hasil => {
console.log('Semua Promise (Janji) telah terpenuhi');
$('.container .alert').removeClass('alert-info').addClass('alert-success').html('Semua data berhasil diambil dari server!');
}, error => {
console.log('Terjadi error karena salah satu Promise tidak bisa terpenuhi!')
$('.container .alert').removeClass('alert-info').addClass('alert-danger').html('Error disebabkan oleh: '+error);
});

</script>
</head>
<body>
<div class="container"><div class="alert alert-info">Loading data...</div></div>
</body>
</html>


Ketika kita menggunakan Promise.all, argumen yang digunakan harus berupa Array yang mengandung semua fungsi Promise yang kita eksekusi. Apabila semua fungsi Promise ini berhasil dan terpenuhi (resolve), maka kode di dalam callback pertama fungsi .then akan dieksekusi. Sedangkan apabila salah satu saja gagal alias reject, maka callback kedua akan dijalankan dan pesan error akan muncul. Bagaimana? menarik bukan? sekali kita paham akan pemanfaatan Promise maka kemungkinan besar kita akan banyak memanfaatkannya untuk menuliskan kode yang lebih elegan untuk operasi-operasi asynchronous di kode Javascript kita. Selamat mencoba!

Read More

21 December 2017

Frontend aplikasi web dengan AngularJS dan backend PHP

14:18 0

Sebenarnya topik ini sudah agak basi, tetapi berhubung saya ingin mendokumentasikan "eksperimen" saya pada framework frontend dan backend untuk pengembangan aplikasi berbasis web, maka saya tetap ingin menulis artikel ini. Bagi teman-teman yang belum mengenal framework AngularJS, bisa membaca FAQ-nya di halaman FAQ AngularJS. Intinya AngularJS adalah framework untuk membangun antarmuka aplikasi web berbasis Javascript. Ada dua versi Angular, AngularJS (versi 1) dan Angular (versi 2) yang full terintegrasi dengan Node.js, yang saya bahas adalah versi pertama dimana kita tidak perlu menggunakan Node.js. Kenapa saya memilih versi ini karena versi pertama bisa kita integrasikan dengan project aplikasi web yang sudah dengan backend apapun, dalam artikel ini saya menggunakan PHP.



Instalasi


Untuk menggunakan AngularJS kita perlu mengunduh (download) file Javascript-nya AngularJS terlebih dahulu. Setelah file Javascript AngularJS telah terunduh berikutnya kita tinggal me-link file Javascript tersebut dari dalam kode HTML kita. Pada artikel ini saya menempatkan file angular.min.js pada direktori libs/js/angular.min.js. Apabila kita masukkan pada kode HTML akan seperti ini:

<!doctype html>
<html ng-app="arsipApp"><head>
<title>Aplikasi Web Arsip</title>
<script src="libs/js/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
</head>

Atau apabila aplikasi web kita sudah kita letakkan pada server dan sudah terkoneksi dengan jaringan Internet maka kita bisa memanfaatkan layanan CDN:
<!doctype html>
<html ng-app="arsipApp"><head>
<title>Aplikasi Web Arsip</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
</head>

Pada kode di atas saya juga me-link file HTML dengan framework CSS Bootstrap agar tampilan aplikasi web sedikit lebih nyaman dilihat.

Frontend static


Bagi teman-teman yang sudah menggunakan aplikasi web Gmail atau Google Mail maka akan melihat bahwa Google membangun antarmukanya dengan menggunakan Javascript yang kemungkinan juga merupakan cikal bakal dari lahirnya framework AngularJS ini. AngularJS menganut prinsip MVW (Model-View-Whatever), dimana file HTML merupakan View (tampilan) dan kode Javascript yang mengandung logika aplikasi dan model (controller). Untuk contoh aplikasi web yang saya buat untuk artikel ini saya akan membuat aplikasi web untuk pendataan Arsip sederhana. Untuk melihat cara kerja dari AngularJS ada baiknya kita coba dengan menggunakan halaman web sederhana yang menggunakan data tidak permanen (data tidak disimpan secara permanen ke backend). Buatlah sebuah file HTML dengan nama index.html dan isikan dengan kode HTML berikut:


index.html


<!doctype html>
<html ng-app="arsipApp">
<head>
<title>Aplikasi Web Arsip</title>
<script src="libs/js/angular.min.js"></script>
<script src="controllers/arsip.js"></script>
<link rel="stylesheet" type="text/css" href="libs/bootstrap/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<h2>Aplikasi Arsip</h2>
<hr/>
<div ng-controller="arsipController as arsip">
<input type="text" ng-model="arsip.cari" class="form-control" style="border-radius: 50px;" placeholder="Masukkan kata kunci untuk mencari" />
<hr/>
<h5>Tambah Data Arsip</h5>
<form name="formArsip" ng-submit="arsip.tambah()">
<div class="row">
<div class="col">
<input type="text" ng-model="arsip.inputKode" class="form-control" placeholder="Kode arsip" required />
</div>
<div class="col">
<input type="text" ng-model="arsip.inputJudul" class="form-control" placeholder="Judul arsip" required />
</div>
<div class="col">
<input class="btn btn-primary" type="submit" value="Tambah" ng-disabled="formArsip.$invalid">
</div>
</div>
</form>
<hr/>
<div class="alert alert-info">Jumlah total arsip {{arsip.total()}}</div>
<table class="table table-bordered table-striped">
<thead>
<tr><th>Kode</th><th>Judul</th><th> </th></tr>
</thead>
<tbody>
<tr ng-repeat="data in arsip.data | filter:arsip.cari track by data.kode">
<td>{{data.kode}}</td>
<td>{{data.judul}}</td>
<td><button type="button" class="btn btn-danger" ng-click="arsip.hapus(data.kode)">Hapus</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>


Buatlah sebuah direktori baru dengan nama controllers, dan didalam direktori baru ini buatlah sebuah file Javascript bernama arsip.js. Isikan file tersebut dengan kode berikut:



controllers/arsip.js


/**
* Modul "arsipApp"
* Controller "arsipController"
*/
angular.module('arsipApp', []).controller('arsipController', function() {
// variabel "arsip" merujuk kepada objek/instance dari "arsipController"
var arsip = this;

// controller "arsipController" memiliki property/anggota "data" untuk menampung data arsip
arsip.data = [];

// metode "tambah" untuk menambahkan data arsip
arsip.tambah = function() {
arsip.data.push({kode: arsip.inputKode, judul:arsip.inputJudul});
arsip.inputJudul = '';
arsip.inputKode = '';
};

// metode "hapus" untuk menghapus data arsip terpilih
arsip.hapus = function() {
var konf = confirm('Yakin akan menghapus data ini?');
if (konf) {
arsip.data.splice(this.$index, 1);
}
};

// metode "total" untuk mendapatkan jumlah total data arsip
arsip.total = function() {
var count = arsip.data.length;
return count;
};
});


Pada kode HTML index.html coba perhatikan pada atribut tag yang saya berikan warna kuning, atribut-atribut tersebut adalah atribut spesifik AngularJS atau biasa juga disebut directive. Atribut ng-app contohnya menandakan bahwa halaman web ini menggunakan modul arsipApp yang kita definisikan pada file controllers/arsip.js, sedangkan atribut ng-controller menetapkan bahwa semua yang berada di dalam scope atau cakupan dari tag tersebut bisa menggunakan controller arsipController yang instance/objek-nya bernama arsip sebagaimana tertulis arsipController as arsip. Atribut ng-repeat kita gunakan untuk melakukan iterasi/loop data. Atribut ng-model mengikat (binding) tag tersebut ke properti yang namanya didefinisikan di dalamnya. Atribut ng-click, ng-submit merupakan atribut terkait event yang terjadi pada browser, dimana nilai atribut-atribut ini biasanya memanggil metode-metode yang sudah kita definisikan pada controller arsipController. Adapun untuk menampilkan nilai (value) dari suatu variabel Javascript pada AngularJS kita menggunakan ekspresi {{namaVariabel}}. Apabila kita buka file index.html pada browser maka kita akan melihat tampilan seperti berikut ini:





Coba isikan beberapa data arsip untuk melihat hasilnya.



Frontend Dinamis dengan Backend server


Sayangnya pada contoh aplikasi yang kita buat sebelumnya, data arsip yang kita buat tidaklah permanen karena aplikasi sebenarnya hanya berjalan di sisi client saja (browser), sehingga ketika browser kita tutup maka data arsip yang sudah kita masukkan hilang. Agar kita bisa menyimpan data arsip secara permanen maka kita harus menggunakan backend server, salah satunya dengan menggunakan PHP. Kita bisa juga menggunakan solusi penyimpanan data cloud seperti Firebase atau Google Cloud. Untuk contoh kali ini kita akan membuat backend sendiri dengan menggunakan PHP dan database SQLite. Buatlah sebuah folder pada direktori web server dengan nama testws dan di dalamnya buatlah file PHP dengan nama index.php, db.php, post.php dan sebuah direktori kosong dengan nama db (sebagai tempat file database SQLite_. Isikan file index.php dengan kode sebagai berikut:



htdocs/testws/db.php


<?php
// koneksi ke database SQLite3
try {
$pdo = new PDO('sqlite:./db/arsip.sq3', null, null, array(PDO::ATTR_PERSISTENT => true));
} catch(Exception $e) {
$error = array('error' => 'Gagal terkoneksi ke database karena '.$e);
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($error); die();
}

// buat tabel apabila belum ada
$table_def = 'CREATE TABLE IF NOT EXISTS arsip (kode VARCHAR PRIMARY KEY, judul VARCHAR NOT NULL)';
$create = $pdo->exec($table_def);
if ($create === false) {
$error = array('error' => 'Error ketika membuat tabel!');
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($error); die();
}


Script PHP index.php melakukan koneksi ke database SQLite dengan nama arsip.sq3 dan membuat tabel arsip apabila belum ada sebelumnya.



htdocs/testws/index.php


<?php
// koneksi ke database SQLite3
require 'db.php';

// ambil data
$json = array();
$select_str = 'SELECT * FROM arsip';

// filter data berdasarkan kata kunci pencarian
$filter = filter_input(INPUT_GET, 'katakunci');
if ($filter) {
$select_str .= " WHERE kode LIKE '$filter%' OR judul LIKE '%$filter%'";
}
$query_data = $pdo->query($select_str);
while ($row = $query_data->fetch(PDO::FETCH_ASSOC)) {
$json[] = $row;
}

// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($json); die();


Script PHP index.php menampilkan data dalam format JSON.



htdocs/testws/post.php


<?php
// koneksi ke database SQLite3
require 'db.php';

// masukkan data
$post_data = file_get_contents('php://input');
$input = json_decode($post_data);
if (is_object($input)) {
$sth = $pdo->prepare('REPLACE INTO arsip VALUES (:kode, :judul)');
$data = array(':kode' => $input->kode, ':judul' => $input->judul);
$sth->execute($data);

$json = array('status' => 'sukses');
} else {
$json = array('status' => 'gagal');
}

// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Access-Control-Allow-Methods: POST');
header('Content-type: application/json');
echo json_encode($json); die();


Script PHP post.php menerima data dalam format JSON melalui front end AngularJS untuk dimasukkan ke database SQLite.




htdocs/testws/delete.php


<?php
// koneksi ke database SQLite3
require 'db.php';

// masukkan data
$kode_delete = file_get_contents('php://input');;
if (!empty($kode_delete)) {
$sth = $pdo->prepare('DELETE FROM arsip WHERE kode=:kode');
$data = array(':kode' => $kode_delete);
$sth->execute($data);

$json = array('status' => 'sukses');
} else {
$json = array('status' => 'gagal');
}

// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Access-Control-Allow-Methods: DELETE');
header('Content-type: application/json');
echo json_encode($json); die();


Script PHP delete.php menghapus record arsip pada database SQLite sesuai dengan kode yang dikirim melalui front end AngularJS. Kita juga harus mengubah kode controller Javascript kita pada file arsip.js agar menggunakan service $http yang disediakan oleh AngularJS untuk melakukan request AJAX ke backed server PHP yang sudah kita buat.



controllers/arsip.js


/**
* Modul "arsipApp"
* Controller "arsipController"
*/
angular.module('arsipApp', []).controller('arsipController', function($scope, $http) {
// variabel "arsip" merujuk kepada objek/instance dari "arsipController"
var arsip = this;

// controller "arsipController" memiliki property/anggota "data" untuk menampung data arsip
arsip.data = [];
// ambil data arsip dari server
$http.get('http://localhost/testws/index.php').then(function(response) {
arsip.data = response.data;
});

// metode "tambah" untuk menambahkan data arsip
arsip.tambah = function() {
var baru = {kode:arsip.inputKode, judul:arsip.inputJudul};
var updateIndex = arsip.data.findIndex(function(obj) {
return obj.kode == arsip.inputKode;
});
$http.post('http://localhost/testws/post.php', angular.toJson(baru))
.then(function() {
if (updateIndex > -1) {
arsip.data[updateIndex].kode = arsip.inputKode;
arsip.data[updateIndex].judul = arsip.inputJudul;
} else {
arsip.data.push(baru);
}
arsip.inputJudul = '';
arsip.inputKode = '';
}, function() {
alert('Data gagal dimasukkan ke database');
});
};

// metode "hapus" untuk menghapus data arsip terpilih
arsip.hapus = function(kode) {
var deleteIndex = arsip.data.findIndex(function(obj) {
return obj.kode == kode;
});
var konf = confirm('Yakin akan menghapus data ini?');
if (konf) {
$http.delete('http://localhost/testws/delete.php', {data: kode})
.then(function() {
arsip.data.splice(deleteIndex, 1);
}, function() {
alert('Data gagal dihapus ke database');
});
}
};

// metode "ubah" untuk mengubah data arsip
arsip.ubah = function(kode) {
var ubahIndex = arsip.data.findIndex(function(obj) {
return obj.kode == kode;
});
console.log(arsip.inputKode);
arsip.inputJudul = arsip.data[ubahIndex].judul;
arsip.inputKode = arsip.data[ubahIndex].kode;
};

// metode "total" untuk mendapatkan jumlah total data arsip
arsip.total = function() {
var count = arsip.data.length;
return count;
};
});


Pada kode view index.html kita ubah sedikit kode HTML pada bagian tag table menjadi seperti berikut ini:



index.html


...
<table class="table table-bordered table-striped">
<thead>
<tr><th>Kode</th><th>Judul</th><th> </th><th> </th></tr>
</thead>
<tbody>
<tr ng-repeat="data in arsip.data | filter:arsip.cari track by data.kode">
<td>{{data.kode}}</td>
<td>{{data.judul}}</td>
<td><button type="button" class="btn btn-info" ng-click="arsip.ubah(data.kode)">Ubah</button></td>
<td><button type="button" class="btn btn-danger" ng-click="arsip.hapus(data.kode)">Hapus</button></td>
</tr>
</tbody>
</table>
...




Dengan menggunakan kode baru ini maka aplikasi web AngularJS kita telah menggunakan data real-time ke server backend menggunakan PHP dan database SQLite, silahkan dicoba untuk memasukkan data, menghapus dan mengubah data. Selamat coding dan mencoba 😁.

Read More

13 December 2017

Membangun Aplikasi Web dengan Platform MVC Rails (Ruby)

13:44 0

Ruby dikenal sebagai salah satu bahasa pemrograman yang relatif mudah dipelajari. Salah satu framework Model-View-Controller yang cukup populer berbasis Ruby adalah Rails. Kali ini saya tertarik untuk mendokumentasikan pengembangan aplikasi web dengan menggunakan framework Rails. Untuk menggunakan Rails tentunya kita harus memastikan bahwa Ruby sudah terinstall pada Komputer/PC kita. Ruby pada sistem operasi GNU/Linux, macOS dan beberapa varian UNIX lain biasanya sudah terinstall secara default, sedangkan bagi pengguna sistem operasi Windows harus menginstall Ruby terlebih dahulu melalui RubyInstaller. Bagi pengguna macOS seperti saya ada baiknya menginstall Homebrew terlebih dahulu, untuk memudahkan instalasi perangkat lunak tambahan pihak ketiga seperti Rails. Ada beberapa persyaratan perangkat lunak yang harus tersedia sebelum kita mulai menggunakan Rails yang instalasinya akan saya jelaskan pada paragraf-paragraf berikutnya. Pastikan komputer/PC kita terkoneksi dengan jaringan Internet untuk melalui tahapan proses instalasi Rails.



Instalasi


GNU/Linux


Pengguna GNU/Linux dengan distro-distro populer seperti Ubuntu, Debian, CentOS, SuSe, RedHat, dsb. dapat menginstall Rails dengan mudah menggunakan aplikasi package-manager bawaan. Seperti pada Ubuntu 16.04 kita jalankan perintah-perintah berikut ini secara berurutan pada aplikasi console/terminal:

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs yarn
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL
rbenv install 2.4.2
rbenv global 2.4.2
gem install bundler
gem install rails
rbenv rehash

Wwweeeeww panjang yak! 😂😂😂. Kalau tidak ada masalah dalam proses perjalanan instalasinya maka Rails siap digunakan.



Apple macOS


Tahapan paling pertama adalah pastikan bahwa kita sudah menginstall Xcode dan command-line toolsnya (bisa didownload gratis melalui laman resmi Apple di https://developer.apple.com/xcode/ (ukuran file instalasi Xcode besar, pastikan mengunduh dengan menggunakan jaringan WiFi atau LAN, kecuali paket data 4G Anda unlimited FUP-nya :D ). Apabila Xcode sudah terinstall berikutnya buka Terminal dan jalankan:

xcode-select --install

Akan muncul dialog terkait dengan lisensi yang harus kita setujui. Pengguna GNU/Linux, UNIX, ataupun Windows tidak perlu melakukan tahap ini.



Khusus pengguna Apple macOS jangan lupa meng-install Homebrew pada macOS dengan membuka aplikasi Terminal dan jalankan perintah berikut:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"



Berikutnya jangan lupa mengupdate "gem" (package manager khusus library Ruby) ke versi terbaru:

sudo gem update --system



Lagi-lagi Khusus pengguna Apple macOS, tahap berikutnya kita perlu menginstall library libxml2 dari Homebrew, karena entah kenapa di macOS High Sierra (11.13.1) dengan Xcode versi teranyar selalu gagal di proses kompilasi library Nokogiri (parser HTML dan XML) karena libxml2 yang tidak cocok.

brew install libxml2
sudo gem install -n /usr/local/bin nokogiri -- --use-system-libraries --with-xml2-include=$(brew --prefix libxml2)/include/libxml2



Setelah semua sukses diinstall baru kemudian kita install Rails dan Bundler dengan perintah:

sudo gem install -n /usr/local/bin rails
sudo gem install -n /usr/local/bin bundler


Tunggu proses hingga selesai. Apabila tidak muncul galat/error selama prosesnya makan Rails berhasil terinstall di Komputer/PC kita. Kemungkinan besar Anda akan bertanya apa itu "Bundler"? Bundler adalah dependancy manager semua gems (library Ruby) untuk project aplikasi yang dibangun dengan Rails. Dengan menggunakan bundle kita memastikan bahwa requirement gems aplikasi web kita terpenuhi.



Microsoft Windows ( versi >= 7)


Instalasi Rails di sistem operasi Windows, bisa dibilang gampang-gampang susah (sebenarnya instalasi di GNU/Linux dan Apple macOS juga tidak bisa dibilang gampang 😂😂😂), karena ada beberapa perangkat lunak pendukung yang harus ada. Berikut langkah-langkahnya:


  1. Install Ruby dengan mengunduh/men-download dan menjalankan installer RubyInstaller. Pastikan opsi "Add Ruby executables to your PATH" dicentang pada saat proses instalasi

  2. Install MSYS2 dari http://www.msys2.org/, karena Rails akan membutuhkan library native Ruby yang dikompilasi dengan compiler C

  3. Unduh/download NodeJS dan jalankan installer-nya dari https://nodejs.org

  4. Buka/cari aplikasi "Start Command Prompt with Ruby" dari RubyInstaller yang terdapat pada menu utama Windows

  5. Pada Command Prompt Ruby ketikkan perintah:
    gem install rails
    gem install bundler


Apabila tidak ada masalah dalam proses perjalanan instalasinya maka Rails siap digunakan.



Membangun Aplikasi Web


Hampir serupa dengan model framework fullstack seperti Meteor yang saya tulis pada artikel sebelumnya, apabila kita akan membuat aplikasi web dengan Rails maka Rails akan membuatkan skeleton/kerangka dari aplikasi kita. Untuk membuat aplikasi web baru dengan Rails, maka pada Terminal jalankan perintah berikut:

rails new aplikasiweb -d sqlite3 -B
cd aplikasiweb/
bundle install

Tunggu sampai proses selesai. Perintah diatas membuat sebuah direktori aplikasi web baru bernama "aplikasiweb" beserta dengan skeleton/kerangka dan semua requirement yang dibutuhkan dan secara default menggunakan database sqlite3 sebagai backend penyimpanan datanya, bagi penggemar MySQL bisa diganti dengan mysql, bagi penggemar PostgreSQL bisa diganti dengan postgresql. SQLite3 dipilih karena dia sangat sederhana, hanya berbasis file dan tidak membutuhkan instalasi perangkat lunak tambahan, cocok untuk aplikasi web sederhana untuk belajar.



Controller dan Views


Ketika membangun aplikasi web berbasis MVC, biasanya saya membuat "Controller" terlebih dahulu, ada juga dengan yang mulai dengan membangun "Model" terlebih dahulu, ini masalah selera dan kebiasaan kalau menurut saya. Controller bisa kita anggap sebagai logika bisnis dari sebuah aplikasi, yang mengatur proses/flow aplikasi berjalan. Untuk membuat controller bernama "Home" dengan sebuah metode bernama "index" kita akan menjalankan perintah berikut:

rails generate controller home index

Setelah menjalankan perintah ini kita akan melihat bahwa rails membuat beberapa file, tetapi yang paling penting adalah file app/controllers/home_controller.rb dan app/views/home/index.html.erb, kedua file ini yang akan kita modifikasi isinya alias coding. Buka file explorer dan kemudian arahkan ke dalam direktori/folder aplikasiweb dan bukalah kedua file tersebut dengan editor teks favorit masing-masing.


Isikan kedua file tersebut dengan kode-kode seperti berikut ini:



app/controllers/home_controller.rb


class HomeController < ApplicationController
def index
@judul = 'Aplikasi Web Rails'
@isi = 'Halo Rails!'
end
end



app/views/home/index.html.erb


<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p><

Fungsi dari file app/views/home/index.html.erb adalah sebagai "views" atau "tampilan" bagi controller "Home" dan metode "index".



Untuk melihat bagaimana aplikasi web sederhana ini berjalan, maka pada Terminal/console, pastikan kita berada di dalam direktori aplikasiweb, jalankan perintah berikut:

rails server -p 9000

Kemudian bukalah browser favorit masing-masing dan arahkan ke URL: http://localhost:9000/home/index dan kita akan melihat hasil seperti gambar berikut:


Apabila pada browser terlihat seperti tampilan di atas maka, selamat! kita sudah berhasil membuat aplikasi web dengan Rails pertama kita!



Sekarang kita ubah coding controller "Home" kita:

app/controllers/home_controller.rb


class HomeController < ApplicationController
# metode index
def index
@judul = 'Aplikasi Web Rails'
@isi = 'Halo Rails!'
end

# metode informasi
def informasi
@judul = 'Halaman Informasi'
@isi = 'Ini adalah halaman informasi terkait dengan aplikasi web yang dibangun dengan Rails. '
@isi << 'Rails adalah framework MVC berbasis Ruby yang banyak digunakan oleh pengembang aplikasi web '
@isi << 'di Internet'

# array daftar framework
@framework = [{:url => 'http://rubyonrails.org/', :text => 'Ruby on Rails'},
{:url => 'https://codeigniter.com/', :text => 'Codeigniter'},
{:url => 'http://www.web2py.com/init/default/index', :text => 'Web2py'}
]
end
end


Kita mendefinisikan metode baru bernama "informasi" yang nantinya akan diakses melalui URL http://localhost:9000/home/informasi. Tetapi sebelum bisa diakses kita perlu membuat sebuah file "views" yang akan menampilkan isi dari metode "informasi". Buatlah file app/views/home/informasi.html.erb dan isikan dengan kode berikut:

app/views/home/informasi.html.erb


<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
<p>Framework MVC populer antara lain:
<ul>
<% @framework.each do |mv| %>
<li><a href="<%= mv[:url] %>"><%= mv[:text] %></a></li>
<% end %>
</ul>
</p>


Kemudian bukalah file config/routes.rb dan ubahlah isi file tersebut menjadi seperti berikut:

config/routes.rb


Rails.application.routes.draw do
root 'home#index'
get 'home/index'
get 'home/informasi'

# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end


Buka browser kemudian arahkan ke URL: http://localhost:9000/home/informasi dan kita akan melihat hasil seperti gambar berikut:


Jangan lupa menambahkan daftar "route" pad file config/routes.rb, setiap kali kita menambahkan metode pada controller agar bisa diakses melalui browser.



Integrasi dengan framework UI (Bootstrap)


Sejauh ini contoh aplikasi yang kita buat tampilannya sangat sederhana, karena kita belum menambahkan CSS di aplikasi kita. Framework seperti Rails menyediakan cara mengintegrasikan framework UI seperti Bootstrap tanpa harus men-setup secara manual. Caranya adalah seperti ini:


  1. Matikan server Rails yang sedang berjalan pada Terminal/console/command prompt dengan menekan "Ctrl+C"

  2. Buka file Gemfile (bukan Gemfile.lock) yang terdapat pada root direktori aplikasi web Rails kita dengan editor teks dan kemudian pada baris akhir tambahkan:

    Gemfile


    # Bootstrap
    gem 'bootstrap', '~> 4.0.0.beta'
    gem 'jquery-rails'


  3. Kembali ke Terminal/console/command prompt, masuk ke direktori aplikasi web kita dan jalankan perintah:

    bundle install
    mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss


  4. Buka file app/assets/stylesheets/application.scss dengan editor teks dan kemudian pada baris akhir tambahkan:

    app/assets/stylesheets/application.scss


    @import "bootstrap";


  5. Buka file app/assets/javascripts/application.js dengan editor teks dan kemudian pada baris akhir tambahkan:

    app/assets/javascripts/application.js


    //= require jquery3
    //= require popper
    //= require bootstrap


  6. Hidupkan kembali server Rails dengan perintah:

    rails server -p 9000




Sebelum kita lihat efek perubahan halaman web kita dengan terinstallnya Bootstrap, mari kita ubah dulu kode di beberapa file views kita menjadi seperti berikut ini:

app/views/home/index.html.erb


<div class="jumbotron jumbotron-fluid" style="background-image: url('/bg.jpg'); background-size: cover;">
<div class="container">
<h1 class="display-3">Selamat Datang</h1>
<p class="lead">Ruby on Rails!</p>
</div>
</div>
<div class="container">
<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
</div>



app/views/home/informasi.html.erb


<div class="container">
<h1 class="text-center"><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
<p>Framework MVC populer antara lain:
<ul>
<% @framework.each do |mv| %>
<li><a href="<%= mv[:url] %>"><%= mv[:text] %></a></li>
<% end %>
</ul>
</p>
</div>



Buatlah dua file views baru, masing-masing bernama _main_menu.html.erb dan _footer.html.erb, dan letakkan kedua file ini pada direktori app/views/layouts/ dan isikan masing-masing dengan kode berikut:

app/views/layouts/_main_menu.html.erb


<nav class="navbar navbar-dark bg-dark">
<a class="navbar-brand" href="/">Aplikasi Web Rails</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="mainMenu">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="/">Beranda</a></li>
<li class="nav-item"><a class="nav-link" href="/home/informasi">Informasi</a></li>
</ul>
</div>
</nav>



app/views/layouts/_footer.html.erb


<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-3">Selamat Datang</h1>
<p class="lead">Ruby on Rails!</p>
</div>
</div>
<div class="container">
<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
</div>



Kemudian bukalah file app/views/layouts/application.html.erb yang merupakan file views layout utama aplikasi Rails dan isikan dengan kode berikut:

app/views/layouts/application.html.erb


<!DOCTYPE html>
<html>
<head>
<title>Aplikasi Web Rails</title>
<meta name="dc.creator" content="Aditya Dees" />
<%= csrf_meta_tags %>

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

<body>
<%= render "layouts/main_menu" %>
<%= yield %>
<%= render "layouts/footer" %>
</body>
</html>



File views app/views/layouts/_main_menu.html.erb dan app/views/layouts/_footer.html.erb dalam terminologi Rails disebut sebagai "partial views", yaitu file views yang merupakan potongan-potongan untuk dimasukkan ke dalam file views lain, dalam hal ini kedua file tersebut kita masukkan ke dalam file views app/views/layouts/application.html.erb dengan menggunakan perintah render. Tanda underscore ditiadakan ketika kita meng-include "partial views" dengan perintah render. Apabila semua kode telah kita tuliskan dengan benar maka kita akan melihat hasil aplikasi web kita menjadi seperti berikut ini:











 


Bisa kita lihat setelah diintegrasikan dengan Bootstrap, tampilan aplikasi web kita menjadi lebih bagus dan tentunya menjadi responsive secara otomatis.



Model


Kita sudah melihat bagaimana cara kerja controller dan views pada Rails, dan tentunya aplikasi web yang dinamis akan memiliki konten yang dibuat secara dinamis juga, dimana konten-konten dinamis ini biasanya disimpan dan diambil dari database. Model dalam hal ini mendefinisikan bagaimana data dari sebuah aplikasi dibuat, diambil/dibaca, diubah dan dihapus atau bahasa kerennya operasi CRUD (Create, Read, Update, Delete). Untuk lebih jelasnya mengenai bagaimana pemanfaatan Model di Rails akan saya tuliskan pada artikel berikutnya :).

Read More

18 November 2017

Membangun Aplikasi Web dengan Platform Javascript Fullstack Meteor

09:33 0


Sudah lama tidak menulis blog, rasanya kangen juga ingin menulis sesuatu. Kebetulan disuruh oleh sensei (supervisor PhD) untuk belajar bahasa pemrograman baru untuk web programming, setelah baca-baca prosiding konferensi ACM CHI Conference on Human Factors in Computing Systems 2017, salah satu paper menuliskan tentang pengembangan prototipe aplikasi berbasis web untuk kolaborasi pemrograman web dan platform yang mereka gunakan untuk membangun aplikasi tersebut adalah platform berbasis server side Javascript NodeJS, Meteor. Akhirnya saya tertarik untuk mencoba membangun aplikasi dengan menggunakan Meteor dan sekalian mencoba mendokumentasikan pengembangan aplikasi dengan menulis artikel blog ini, dan siapa tahu bermanfaat untuk teman-teman yang membacanya, terutama yang sedang mencari, ehhhmmmm... bahasa pemrograman baru :D .

Sebelumnya kita mulai ada baiknya kita kenal dulu apa itu Meteor sebenarnya. Seperti saya kutip dari dokumentasi terakhir Meteor, Meteor adalah:



Meteor is a full-stack JavaScript platform for developing modern web and mobile applications... Meteor uses data on the wire, meaning the server sends data, not HTML, and the client renders it.


Konsep hampir serupa dengan data on the wire sebenarnya juga diterapkan pada beberapa framework Javascript seperti AngularJS dan ReactJS, dimana data dari server tidak dikirim dalam bentuk kode HTML, tetapi dalam bentuk data seperti JSON (JavaScript Object Notation) dan kemudian data dari server diformat ke dalam kode HTML yang diproses oleh library Javascript di sisi klien, membuat beban komunikasi server dan klien menjadi lebih ringan karena hanya berkomunikasi dalam format data ringan seperti JSON. Meteor pada intinya adalah sebuah platform fullstack yang intinya adalah NodeJS, beserta dengan beberapa komponennya, termasuk juga Meteor sudah menyediakan server MongoDB sehingga kita tidak perlu lagi install MongoDB sebagai server terpisah. (sisi negatifnya adalah ukuran download Meteor yang besar dan harus di-download melalui terminal/command line).



Untuk mengembangkan aplikasi web dengan menggunakan Meteor, ada beberapa hal yang sebaiknya kita kuasai terlebih dahulu yaitu: HTML5, CSS, Javascript, jQuery dan MongoDB. Jangan lupa juga menginstall text editor pemrograman favorit masing-masing untuk menuliskan kode-kode Javascript Meteor nanti.



Instalasi


Untuk menggunakan platform Meteor maka kita harus menginstallnya terlebih dahulu dengan menggunakan terminal/console/command prompt/powershell. Pada tulisan ini saya menggunakan aplikasi Terminal pada Operating System (OS) Apple macOS High Sierra dan kemudian menjalankan perintah:

curl https://install.meteor.com/ | sh

Pengguna OS GNU/Linux dengan berbagai distro-nya bisa menjalankan perintah yang sama, pastikan bahwa curl sudah terinstall, apabila belum, install terlebih dahulu dengan menggunakan package manager distro masing-masing.



Bagi pengguna OS Microsoft Windows, ada perangkat lunak tambahan untuk menginstall Meteor yaitu Chocolatey. Chocolatey merupakan package manager/software installer untuk platform Windows. Cara instalasi Chocolatey silahkan ikuti buka tautan/link ke cara instalasi Chocolatey. Setelah Chocolatey terinstall maka langkah berikutnya adalah menjalankan perintah berikut pada command prompt/powershell Windows:

choco install meteor



Persiapan Kerangka Struktur Aplikasi


Setelah Meteor sudah terinstall, maka kita bisa mulai untuk membuat aplikasi web Javascript pertama kita. Untuk contoh aplikasi web yang akan kita kembangkan adalah aplikasi sederhana untuk membuat agenda kegiatan. Pada Terminal jalankan perintah berikut ini secara berurutan:

mkdir meteorapp
cd meteorapp
meteor create agendakegiatan
cd agendakegiatan



Saat ini kita sedang berada di dalam folder/direktori agendakegiatan dan kita akan melihat bahwa pada folder ini Meteor sudah membuat kerangka dasar aplikasi web kita (skeleton), yang terdiri atas folder client, server, node_modules, dan file package-lock.json dan package.json. Kita akan banyak bermain di dalam folder client, server dan satu buah folder ini tempat kita akan banyak menyimpan berbagai kode Javascript yaitu imports. Folder client adalah folder yang mengandung semua file terkait dengan apa yang akan ditampilkan kepada browser, sedangkan folder server mengandung semua file terkait dengan pemrosesan di sisi server.


Karena folder imports belum ada, maka kita perlu membuatnya terlebih dahulu, sekaligus kita membuat folder-folder lain di bawahnya dengan menjalankan perintah-perintah berikut:


mkdir imports
cd imports
mkdir ui
mkdir api



Setelah kita selesai membuat folder-folder baru tersebut, maka selanjutnya kita juga perlu membuat beberapa file tambahan yang akan kita isikan dengan kode Javascript dan kode HTML. Jalankan perintah-perintah berikut ini untuk membuat file-file tersebut:

touch ui/body.html
touch ui/body.js
touch api/agenda.js



Coding


Saatnya kita mulai menuliskan kode-kode! Buka text editor favorit masing-masing dan bukalah file-file berikut ini (relatif terhadap direktori agendakegiatan :



  1. client/main.html

  2. client/main.js

  3. client/main.css

  4. imports/ui/body.html

  5. imports/ui/body.js

  6. imports/api/agenda.js

  7. server/main.js


Berikutnya silahkan ubah dan isikan masing masing file dengan kode-kode berikut.



client/main.html


<head>
<title>Aplikasi Agenda Kegiatan</title>
<meta name="author" content="Aditya Dees"/>
<meta name="keywords" content="Meteor, Javascript, Agenda, Aplikasi Web"/>
</head>


client/main.js


import '../imports/ui/body.js';


imports/ui/body.html


<body>
<div class="ui container">
<h2 class="ui block header">Agenda Kegiatan</h2>

<div class="ui container segment">
<form class="ui form form-kegiatan">
<div class="three fields">
<div class="field">
<label>Nama Kegiatan</label>
<input type="text" name="nama_kegiatan" class="form-text form-control" placeholder="Nama kegiatan" />
</div>
<div class="field">
<label>Tanggal Kegiatan</label>
<input type="text" name="tgl_kegiatan" class="form-text form-control" placeholder="Tanggal kegiatan" />
</div>
<div class="field">
<label>Lokasi Kegiatan</label>
<input type="text" name="lokasi_kegiatan" class="form-text form-control" placeholder="Lokasi kegiatan" />
</div>
</div>
<input type="hidden" name="_id" value="" />
</form>

<table class="ui celled table">
<thead>
<tr>
<th class="ten wide">Nama Kegiatan</th>
<th>Tanggal</th>
<th>Lokasi</th>
<th class="one wide"> </th>
</tr>
</thead>
<tbody>
{{#each agenda}}
{{> data}}
{{/each}}
</tbody>
</table>

</div>
</div>
</body>

<template name="data">
<tr>
<td><a class="edit-button" data-id="{{_id}}" href="#">{{kegiatan}}</a></td>
<td>{{tgl}}</td>
<td>{{lokasi}}</td>
<td><button class="ui icon button delete"><i class="trash icon"></i></button></td>
</tr>
</template>


imports/ui/body.js


import { Template } from 'meteor/templating';
import { Agenda } from '../api/agenda.js';
import './body.html';

Template.body.helpers({
agenda() {
return Agenda.find({}, { sort: { tgl: -1 } });
}
});

Template.body.events({
'keypress .form-text'(event) {
// event.preventDefault();
// console.log(event);
const enterKey = event.key == "Enter";
// console.log(enterKey);
if (enterKey) {
// ambil objek form
const form = $('.form-kegiatan');

// ambil nilai form
const kegiatan = form.find('[name="nama_kegiatan"]');
const tgl = form.find('[name="tgl_kegiatan"]');
const lokasi = form.find('[name="lokasi_kegiatan"]');
const _id = form.find('[name="_id"]');

if (!kegiatan.val() || !tgl.val() || !lokasi.val()) {
return false;
}

// console.log(form);

if (_id.val().trim() != '') {
// masukkan ke database
Agenda.update(
{_id: _id.val()},
{ kegiatan: kegiatan.val(),
tgl: tgl.val(),
lokasi: lokasi.val(),
});
} else {
// masukkan ke database
Agenda.insert({
kegiatan: kegiatan.val(),
tgl: tgl.val(),
lokasi: lokasi.val(),
tgl_input: new Date(),
});
}

// reset nilai form
kegiatan.val('');
tgl.val('');
lokasi.val('');
_id.val('');
}
}
});

Template.data.events({
'click .delete'(event) {
const confirmDelete = confirm('Yakin akan menghapus data ini?');
if (confirmDelete) {
Agenda.remove(this._id);
}
},
'click .edit-button'(event) {
const updateData = Agenda.findOne({_id: this._id});
// console.log(updateData);
const form = $('.form-kegiatan');
const kegiatan = form.find('[name="nama_kegiatan"]');
const tgl = form.find('[name="tgl_kegiatan"]');
const lokasi = form.find('[name="lokasi_kegiatan"]');
const _id = form.find('[name="_id"]');
kegiatan.val(updateData.kegiatan);
tgl.val(updateData.tgl);
lokasi.val(updateData.lokasi);
_id.val(this._id);
}
});


imports/api/agenda.js


import { Mongo } from 'meteor/mongo';
export const Agenda = new Mongo.Collection('agenda');


server/main.js


import '../imports/api/agenda.js';


client/main.css


body {
margin: 0; padding: 0;
top: 0; bottom: 0;
left: 0; right: 0;
position: absolute;
min-height: 100%;
font-family: Helvetica, sans-serif, Arial;
background: #777;
}

.container {
position: relative;
margin: 0 auto;
width: 600px;
background: #ccc;
height: 100%;
}

.header {
text-align: center;
background: linear-gradient(180deg, #555, #999);
margin: 0;
color: #fff;
padding: 20px;
}

.field {
clear: both;
}

.field label {
padding: 5px;
display: block;
float: left;
width: 24%;
}

.field input {
padding: 5px;
display: block;
float: right;
width: 72%;
font-size: 1.1em;
border: 0;
border-bottom: 1px solid #ccc;
}

.table {
width: 100%;
border-spacing: 0;
}

.celled thead tr th {
padding: 10px;
border-bottom: 1px solid #333;
background: linear-gradient(180deg, #555, #999);
margin: 0;
color: #fff;
}

.celled tbody tr td {
margin: 0;
padding: 9px;
border-bottom: 1px solid #777;
}

.button {
display: inline-block;
width: 100%;
font-size: 1.2em;
}


Ujicoba Aplikasi


Setelah semua kode sudah kita tuliskan maka berikutnya adalah mengujicoba apakah aplikasi sudah berjalan dengan baik. Untuk menjalankan aplikasi dengan Meteor, buka kembali Terminal/console, masuk ke dalam folder aplikasi agendakegiatan dan kemudian jalankan perintah:

meteor

maka kemudian kita akan melihat status seperti ini pada Terminal/console kita:



Selanjutnya buka browser favorit masing-masing dan arahkan ke alamat URL: http://localhost:3000, dan kita akan melihat aplikasi web kita sudah berjalan dengan tampilan seperti ini:




Coba isikan data pada kotak input isian nama kegiatan, tanggal kegiatan dan lokasi kegiatan dan kemudian tekan Enter untuk melihat menyimpan data isian kita. Kita lihat bahwa setelah kita menekan tombol Enter, maka data yang kita masukkan langsung muncul pada tabel di bawah form isian tanpa terjadi reload halaman! Dan yang lebih menarik bahwa apabila kita menjalankan dua browser yang berbeda bersamaan, ketika kita mengupdate data pada satu browser, maka otomatis tampilan pada browser lain akan otomatis terupdate tanpa harus me-refresh/reload browser tersebut! Hal ini terjadi karena aplikasi yang dibangun dengan Meteor telah menerapkan konsep push dari server ke client. Silahkan lihat pada video di bawah ini untuk melihat demo push data pada Meteor:





Bagaimana? menarik bukan membangun aplikasi dengan menggunakan Meteor? Mengenai penjelasan lebih detail mengenai masing-masing kode, akan saya coba tulis pada artikel berikutnya, selamat mencoba dan semoga bermanfaat!


Read More

https://payclick.com/

Contact us for advertising.