{{ message }}

Tutorial Membuat Aplikasi WordPress Reader Dengan JQuery dan VueJS

30/07/2017 | Javascript
Tutorial Membuat Aplikasi WordPress Reader Dengan JQuery dan VueJS

WordPress.com adalah platform populer untuk membuat sebuah blog. Ada jutaan konten terdapat disana dan mungkin juga Anda sendiri memiliki blog di wordpress.com. Kabar baiknya adalah sekarang wordpress.com menyediakan public API untuk mengakses konten blog-nya bahkan juga dapat memanipulasi isi-nya dengan izin otentifikasi tentunya. Experiment kita kali ini adalah membuat aplikasi WordPress Reader yaitu aplikasi Resep Masakan dengan mengambil konten dari sebuah blog Resep Masakan. Kita akan memanfaatkan WordPress Public API, JQuery, Ajax dan Vue JS untuk membuatnya. Bagi Anda yg memiliki blog di wordpress.com dan ingin membuat aplikasi Android-nya mungkin tutorial ini akan berguna.

Experiment kita kali ini adalah membuat aplikasi Resep Masakan sederhana, yg datanya kita ambil dari blog resep masakan yg pernah saya buat yaitu http://reseproso.wordpress.com. Yg nantinya setelah selesai kita buat mungkin dapat Anda compile menjadi aplikasi android APK. Berikut ini mekanisme aplikasinya;

  1. List Resep Masakan
    Menampilkan list resep masakan berupa gambar dan nama masakan. Disini kita mengambil konten resep masakan ke blog wordpress melalui AJAX lalu menampilkannya
  2. Detail Resep Masakan
    Ketika salah satu resep masakan di list di klik maka kita akan menampilkan resep yg di-klik tersebut dengan satu konten penuh.

Yg pertama kita persiapkan adalah meload library yg diperlukan yaitu;

  1. JQuery
    Library yg digunakan untuk melakukan pemanggilan WordPress Public API melalui AJAX
  2. Bootstrap
    Untuk mengatur tampilan agar mobile friendly
  3. VueJS
    Sebagai library utama interaksi dan output rendering

Berikut ini kode awal untuk me-load seluruh library yg diperlukan;

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>WP Reader</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 
  <!-- Libraries -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu+Condensed">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 
  <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
 
</head>
<body>
 <!-- Kita akan melanjutkan script disini -->
</body>
</html>

Pentingnya viewport pada line 6 di source code di atas agar aplikasi tidak di zoom out ketika dibuka melalui smartphone. Setelah itu kita tambahkan HTML dan CSS untuk membuat layout yg diperlukan;

...
...
<!-- Style -->
  <style>
  * {
    font-family: 'Ubuntu Condensed';
  }
 
  body {
    margin: 0;
  }
 
  img {
    max-width: 100%;
  }
  </style>
 
</head>
<body>
  <div class="container-fluid">
 
  <div class="navbar navbar-default">
    <h1 style="text-align: center">Resep Masakan</h1>
  </div>
 
  <div id="content" role="main" class="ui-content">
    <component :is="page"></component>
  </div>
 
  <div class="navbar navbar-default" style="text-align: center">
    <br><b>Copyright &copy; By QaiserLab 2016-2017</b><br>&nbsp;
  </div>
</div>
 
...
...

Berikut ini beberapa penjelasan yg perlu diketahui dari source code diatas;

  1. Line 20 s/d 33
    Adalah layout utama yg berisi bagian-bagian layout yaitu header, konten dan footer.
  2. Line 27
    Adalah hal yg peling penting, disini adalah tag komponen yg dapat kita umpamakan adalah kontainer dari halaman yg akan dibuka. Isinya dapat berubah-berubah dengan dikontrol oleh VueJS, anggap saja ini adalaah kontainer halaman yg halaman-nya dapat berpindah-pindah dengan cara mengisi komponen dengan template yg berbeda sesuai dengan halaman yg mau ditampilkan. Dalam hal ini ada 2 halaman penting yg akan ditampilkan nanti, yaitu halaman list dan halaman detail.

Berikut ini pada bagian footer akan kita isi dengan VueJS;

...
...
<div id="content" role="main" class="ui-content">
  <component :is="page"></component>
</div>
 
<div class="navbar navbar-default" style="text-align: center">
  <br><b>Copyright &copy; By QaiserLab 2016-2017</b><br>&nbsp;
</div>
</div>
 
<!--  Template halaman List Resep Masakan -->
<template id="template-list">
<button style="width: 100%" class="btn btn-primary" type="button" @click="reloadItems">{{ state }}</button>
<br>
 
<a
   @click="detailItem"
   href="javascript:"
   class="media"
   v-for="item in items"
   data-id="{{ item.ID }}">
 
  <div class="media-body" style="text-align: center;">
    <img style="width: 300px" src="{{ item.featured_image }}">
    <h4 class="media-heading" style="font-size: 24px">{{ item.title }}</h4>
  </div>
</a>
</template>
 
<!-- Template halaman Detail Resep Masakan -->
<template id="template-detail">
<div class="row">
  <div class="col-md-12">
  <h1>{{ item.title }}</h1>
  {{{ item.content }}}
    <br>
  <button class="btn btn-primary" style="width: 100%" type="button" @click="backToList">Kembali</button>
  </div>
</div>
</template>
 
<!-- Script dimulai -->
<script type="text/javascript">
  var activeItem = {};
  // List Resep Masakan
  var pageList = Vue.component('page-list', {
    template: '#template-list',
    data: function () {
      return {
        state: '',
        items: [],
        activeItem: {},
      };
    },
 
    ready: function () {
 
      this.reloadItems();
 
      $("html, body").animate({ scrollTop: 0 }, "slow");
    },
 
    methods: {
 
      reloadItems: function () {
 
        var wpBlog = 'reseproso.wordpress.com';
        var url = 'https://public-api.wordpress.com/rest/v1.1/sites/' + wpBlog + '/posts/';
 
        this.state = 'Loading...';
 
        $.get(url, function(result) {
          this.items = result.posts;
          this.state = 'Segarkan';
        }.bind(this));
 
      },
 
      detailItem: function (event) {
        this.activeId = $(event.currentTarget).data('id');
 
        $.each(this.items, function (i, item) {
          if (item.ID == this.activeId) {
            this.activeItem = item;
 
          }
        }.bind(this));
 
        activeItem = this.activeItem;
        content.page = 'page-detail';
      },
 
    },
  });
 
  // Meregistrasi template halaman detail menjadi tag <page-detail>
  Vue.component('page-detail', {
    template: '#template-detail',
    data: function () {
      return {
        item: {
          title: '',
          content: '',
        },
      };
    },
 
    ready: function () {
      this.item = activeItem;
      $("html, body").animate({ scrollTop: 0 }, "slow");
    },
 
    methods: {
 
      backToList: function () {
        content.page = 'page-list';
      },
    },
  });
 
  var content = new Vue({
    el: '#content',
    data: {
      page: 'page-list',
    },
 
  });
 
</script>
 
</body>
</html>

Penjelasan script;

  1. Line 45
    Mempersiapkan variable penampung data dari salah satu resep masakan yg akan di klik nanti. Guna untuk ditampilkan di halaman detail.
  2. Line 48
    Mengaitkan komponen page-list yg kita buat dengan templatenya yaitu tag dengan selector #template-list, yg terdapat pada line 13.
  3. Line 57 s/d 62
    Method ready pada line 57 ini dapat juga disebut Lifecycle Hooks di dalam VueJS, method ini akan otomatis dipanggil ketika dokumen sudah siap dimanipulasi. Oleh karena itu sangat cocok untuk menempatkan kode inisialisasi disini. Dalam kasus ini ketika aplikasi pertama di load saya langsung mengambil dan menampilkan list resep masakan (line 59/memanggil method reloadItems) lalu memposisikan scrollbar ke posisi awal yaitu paling atas (line 61).
  4. Line 66 s/d 78 (Method reloadItems)
    Kita akan mengambil data dengan memanggil API WordPress yaitu data yg ada pada blog reseproso.wordpress.com. Setelah data kita dapatkan dari blog tersebut lalu kita tampilkan data resep masakan tersebut sebagai list di aplikasi kita. Line 68 s/d 69 mempersiapkan alamat url WordPress Public API (Untuk mengetahui API apa saja yg disediakan WordPress Public API silakan baca dokumentasinya di https://developer.wordpress.com/docs/api). Lalu kita memanggil API tersebut dengan JQuery di line 73 dengan method GET. Karena variable items sudah binding dengan tampilan, jadi di line 74 kita hanya perlu memasukan data yg didapat dari API tadi ke variable items maka tampilanpun ikut menampilkan resep masakannya.
  5. Line 80 s/d 92 (Method detailItem)
    Disini kita menangkap salah satu link resep di list resep yg terkena klik oleh pengguna aplikasi, lalu mengambil data ID dari resep yg telah ter-klik. Pada line 83 kita melooping data items kita yg berisi list resep masakan dan ketika menemukan ID yg sama dengan ID resep yg di klik, kita memasukan row dari list yg memiliki ID yg sama tersebut ke variable global yaitu activeItem, variable activeItem ini sebelumnya sudah kita definisikan sebagain variable global di line 45. Perhatikan line 41 disitu kita merubah content.page menjadi ‘page-detail’, sementara di line 4 dan 125 kita sudah binding komponen yaitu tempat untuk menampilkan halamannya. Jadi ketika kita set content.page-nya menjadi ‘page-detail’ maka komponen yg aktif berpindah ke komponen page-detail yaitu line 132 yg juga otomatis merubah tampilan ke halaman detail, dan Lifecycle Hooks ready pun dipanggil di line 143. Lalu dengan mudah kita-pun menampilkan resep masakan yg telah di-klik dengan memasukan variable item yg telah ter-binding dengan tampilan halaman detail dengan data variable global activeItem tadi. Maka resep masakan yg terpilih akan ditampilkan di halaman detail.

Source Code Lengkap

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>WP Reader</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 
  <!-- Libraries -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu+Condensed">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 
  <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
 
  <!-- Style -->
  <style>
  * {
    font-family: 'Ubuntu Condensed';
  }
 
  body {
    margin: 0;
  }
 
  img {
    max-width: 100%;
  }
  </style>
 
</head>
<body>
  <div class="container-fluid">
 
  <div class="navbar navbar-default">
    <h1 style="text-align: center">Resep Masakan</h1>
  </div>
 
  <div id="content" role="main" class="ui-content">
    <component :is="page"></component>
  </div>
 
  <div class="navbar navbar-default" style="text-align: center">
    <br><b>Copyright &copy; By QaiserLab 2016-2017</b><br>&nbsp;
  </div>
</div>
 
<!--  Template halaman List Resep Masakan -->
<template id="template-list">
  <button style="width: 100%" class="btn btn-primary" type="button" @click="reloadItems">{{ state }}</button>
  <br>
 
  <a
     @click="detailItem"
     href="javascript:"
     class="media"
     v-for="item in items"
     data-id="{{ item.ID }}">
 
    <div class="media-body" style="text-align: center;">
      <img style="width: 300px" src="{{ item.featured_image }}">
      <h4 class="media-heading" style="font-size: 24px">{{ item.title }}</h4>
    </div>
  </a>
</template>
 
<!-- Template halaman Detail Resep Masakan -->
<template id="template-detail">
  <div class="row">
    <div class="col-md-12">
    <h1>{{ item.title }}</h1>
    {{{ item.content }}}
      <br>
    <button class="btn btn-primary" style="width: 100%" type="button" @click="backToList">Kembali</button>
    </div>
  </div>
</template>
 
<script type="text/javascript">
  var activeItem = {};
  // List Resep Masakan
  var pageList = Vue.component('page-list', {
    template: '#template-list',
    data: function () {
      return {
        state: '',
        items: [],
        activeItem: {},
      };
    },
 
    ready: function () {
 
      this.reloadItems();
 
      $("html, body").animate({ scrollTop: 0 }, "slow");
    },
 
    methods: {
 
      reloadItems: function () {
 
        var wpBlog = 'reseproso.wordpress.com';
        var url = 'https://public-api.wordpress.com/rest/v1.1/sites/' + wpBlog + '/posts/';
 
        this.state = 'Loading...';
 
        $.get(url, function(result) {
          this.items = result.posts;
          this.state = 'Segarkan';
        }.bind(this));
 
      },
 
      detailItem: function (event) {
        this.activeId = $(event.currentTarget).data('id');
 
        $.each(this.items, function (i, item) {
          if (item.ID == this.activeId) {
            this.activeItem = item;
 
          }
        }.bind(this));
 
        activeItem = this.activeItem;
        content.page = 'page-detail';
      },
 
    },
  });
 
  // Meregistrasi template halaman detail menjadi tag <page-detail>
  Vue.component('page-detail', {
    template: '#template-detail',
    data: function () {
      return {
        item: {
          title: '',
          content: '',
        },
      };
    },
 
    ready: function () {
      this.item = activeItem;
      $("html, body").animate({ scrollTop: 0 }, "slow");
    },
 
    methods: {
 
      backToList: function () {
        content.page = 'page-list';
      },
    },
  });
 
  var content = new Vue({
    el: '#content',
    data: {
      page: 'page-list',
    },
 
  });
 
</script>
 
</body>
</html>