Javascript between Old and New

Sampai beberapa bulan lalu, saya masih bersikeras menggunakan jQuery sebagai penolong utama saya dalam mengurus frontend sebuah web aplikasi. Sampai suatu titik saya benar-benar berubah haluan kalau “saya harus” merubah konsep saya. Tidak hanya karena jQuery sudah terlalu lama, tetapi juga karena semakin besar sebuah page(semakin banyak interaksi dan event), semakin maintainable juga script tersebut.

Saya berharap kemajuan teknolgi sekarang biesa memecahkan hal tersebut. Siapa tahu ada framework yang dapat menolong pengembangan front-end lebih seperti back end, dimana dapat dibagi seperti halnya pendekatan MVC.

Maka sejak beberapa waktu kemarin saya sempat melakukan research beberapa framework baru, sebutlah Angular(v.4), VueJs, dan ReactJS. Berikut adalah sedikit overview dari ketiga framework tersebut.

Angular (NG)

Angular(NG) adalah yang pertama saya datangi, karena saya dulu sempat “menolak” menggunakan Angular sebelumnya. Tetapi ternyata Angular yang baru(versi 2 ke atas)  adalah pengembangan ulang dari Angular sebelumnya, dimana NG sekarang merupakan full fledged enterprise framework untuk mengembangkan Single Page Application(SPA), tidak bisa(mungkin sulit) digabungkan dengan existing project(seperti jQuery yang tinggal di include dengan script di header/body), terlebih kita harus menggunakan TypeScript(TS) untuk menggunakannya. Semua itu akan di compile dalam bentuk HTML, CSS dan juga JS yang sudah dipacking secara otomatis oleh Angular CLI.

Karena memang desain awalnya sebagai model enterprise, NG sendiri sangat kompleks dan memiliki banyak sekali modul-modul yang kadang membuat adopter awal sangat kerepotan karena kekompleksannya, Walau pada akhirnya sama dengan kalau mempelajari bahasa/framework lain “Kita hanya pakai dan perlu mempelajari yang kita pakai saja.”

Sebagai info tambahan, Angular sendiri merupakan framework yang dibuat oleh raksasa internet, Google. Selain itu NG juga menjadi steping stone saya untuk mempelajari IONIC Framework yang mana merupakan Hybrid Framwork untuk membuat Mobile Apps.
URL: https://angular.io/

ReactJS

ReactJS adalah framework kedua yang saya lirik. Framework ini besutan dari raksasa internet lainnya, Facebook. Entah kenapa React ini lumayan ramai digunakan terutama di Indonesia.

React menggunakan Javascript sebagai bahasanya, sehingga tidak perlu belajar scripting lain seperti Typescript dan sama seperti NG, ReactJS juga memiliki framework yang dapat diimplementasikan untuk membuat mobile apps, namanya ReactNative.

Sayang, saya memutuskan untuk menge-drop React karena saya kurang sreg dengan JSX yang dia pakai. Simplenya JSX akan meng-abstraksi DOM dokumen Anda dalam file JS, beberapa style sheetpun demikian. Untuk saya yang suka memisahkan element-element tersebut, ini sesuatu yang big-no, so well yeah… I decided to drop it for now(please no offense). Berbeda dengan NG, katanya react dapat di satukan dengan existing project atau berdiri sendiri menjadi SPA.
URL: https://reactjs.org/

Vue.js

VueJS adalah framework “TERMUDA” dari ketiga framework sekarang yang sedang naik daun(baru sekitar 1-2 tahun pada 2107) . Berbeda dengan yang lain, Vue tidak ada backingan perusahaan besar seperti NG dan React, walau terakhir saya dapat kabar bahwa React mendapat sokongan besar dari Alibaba.

VueJS dapat digunakan langsung(include dengan tag sript) pada existing project/page dan juga dapat digunakan sebagai full frontend framework(mirip seperti Angular) TETAPI Anda tidak perlu menggunakan TS dan yang terpenting tidak menggunakan model abstraksi JSX. Apabila dilihat lebih dekat, struktur code dari Vue sangat mendekati dari Angular. Inilah mengapa akhirnya saya memutuskan untuk mempelajari Vue.

Untuk saat ini Vue sendiri tidak punya sokongan untuk ke arah mobile apps, tetapi rencananya Ionic juga akan mengintegrasikan Vue ke dalam frameworknya.
URL: https://vuejs.org/

Comparing Old-New

Untuk mempermudah, saya membuat sebuah aplikasi simpel, dimana Anda dapat menambah/mengurangi/mengedit pada satu halaman. Data akan tersimpan pada database dan diambil dengan menggunakan AJAX.

Screenya sebagai berikut:

Tampilan awal, list data

Form edit dan juga add

 

Saya membuat dalam 3 versi jQuery, Angular, dan Vue. Masing-masing saya sertakan HTML dan Script-nya(untuk Angular saya tambahkan module.ts-nya).

 

Jquery

Angular

HTML

<div class="container"  style="margin-top: 30px;">
    <div class="text-right">
        <a href="../index.html" class="btn btn-default btn-sm">Back to index</a>
        <button class="btn btn-success btn-sm" (click)="ShowHideForm(true)">Add new</button>
        <button class="btn btn-info btn-sm" (click)="LoadData()">Reload</button>
    </div>

    <!-- FORM edit and update -->
    <form action=""  class="form-horizontal" (submit)="SubmitForm($event)" *ngIf="showForm">
        <div class="form-group">
            <label for="">Name</label>
            <input type="text" class="form-control" name="name" [(ngModel)]="formModel.name" >
        </div>
        <div class="form-group">
            <label for="">Description</label>
            <textarea class="form-control" name="desc" [(ngModel)]="formModel.description" ></textarea>
        </div>
        <div class="form-group text-right">
                <button class="btn btn-default" type="button" (click)="ShowHideForm(false)">Cancel</button>
            <button class="btn btn-primary" type="submit">Save</button>
        </div>
    </form>

    <!-- TABLEE CONTAINER -->
    <table class="table table-striped">
        <thead>
            <tr>
                <th style="width: 200px;">Name</th>
                <th>Description</th>
                <th style="width: 200px;">Description</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let row of recordsData">
                <td>{{ row.name }}</td>
                <td>{{ row.description }}</td>
                <td>
                    <button class="btn btn-default btn-xs" (click)="LoadDataEdit(row.id)">Edit</button>
                    <button class="btn btn-danger btn-xs" (click)="DeleteRow(row.id)">Delete</button>
                </td>
            </tr>
            <tr *ngIf="recordsData.length === 0">
                <td colspan="3" class="text-center">Data not found {{ "" }}</td>
            </tr>
        </tbody>
    </table>
</div>

TS file:

import { Component, OnInit } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http'
import { Subject, Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/toPromise';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {

  apiBaseURL : string = '../';
  // apiBaseURL : string = 'http://localhost/jscomparee/';

  // Container data loaded from server
  recordsData = [];           
  //  identifier form opened or hiden
  showForm : boolean =  false;
  // Model bind to form
  formModel : { 
      id : 0,
      name : "",
      description : ""
    }

  constructor(
    private objHttp : Http
  ) { }

  ngOnInit() {
    //Loading data on load
    this.LoadData();
  }

  // getting list data
  LoadData() {
    this.objHttp.get(this.apiBaseURL + 'get.php').toPromise().then(data => {
      let parsedData : any = data.json();
      if ( parsedData.st === true ){
        this.recordsData = parsedData.msg;
      }
    });
  }

  // Get record instance for edit purpose
  LoadDataEdit(rowID){
    this.objHttp.get(this.apiBaseURL + 'get_instance.php?id=' + rowID).toPromise().then(data => {
      let parsedData : any = data.json();
      if ( parsedData.st === true ){
        this.formModel = parsedData.msg;
        this.showForm = true;
      } else {
        alert(parsedData.msg);
      }
    });
  }

  // Handler for removing row
  DeleteRow(rowID){
    if ( confirm("Do you really want to remove this data?") ){
      this.objHttp.get(this.apiBaseURL + 'del.php?id=' + rowID).toPromise().then(data => {
        let parsedData : any = data.json();
        if ( parsedData.st === true ){
          alert(parsedData.msg);
          this.LoadData();
        } else {
          alert(parsedData.msg);
        }
      });
    }
  }

  // Show hide form also reset it's state
  ShowHideForm(showHide){
    this.showForm = showHide;
    this.formModel = {
      id :0,
      name : "",
      description : ""
    }
  }

  //Save data handler
  SubmitForm(event : Event){
    
    let formData = new FormData();
    for ( let index in this.formModel ){
      formData.append(index, this.formModel[index]);
    }

    this.objHttp.post(this.apiBaseURL + "cu.php", formData).toPromise().then( result => {
      let parsedData = result.json();
      if ( parsedData.st === true ){
        alert(parsedData.msg);
        this.ShowHideForm(false);
        this.LoadData();
      } else {
        alert(parsedData.msg.join("\n"));
      }
    });

    event.preventDefault();
  }
}

Angular app.module.ts file

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { ExampleComponent } from './example/example.component';


@NgModule({
  declarations: [
    AppComponent,
    ExampleComponent
  ],
  imports: [
    BrowserModule,
    HttpModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Vue

Download code: jscomparee-pack

Untuk Angular file-file terdapat di folder “ng4” jalankan “npm install” command untuk memulai dan setelah  selesai jalankan “ng serve –open“. pastikan Anda telah menginstall Angular CLI dan nodeJS.

Compressed & production bundle terdapat di folder “ng4-dist

Coba kita lihat komparasi berikut ini antara Angular dan juga Vue:

Komparasi Script Vuee(kiri) dan Angular(kanan)

Komparasi HTML Vue(kiri) dan Angular(kanan)

Kalau kita lihat kedua framework tersebut memiliki “banyak” kemiripan. itulah mungkin kennapa saya sangat mudah amsuk ke Vue setelah saya mempelajari NG sebelumnya. contoh saja beberapa attribut seperti:

  • *ngIf (NG)/v-If (Vue)
  • *ngFor (NG)/v-for (Vue)
  • ng-[eventname] (NG)/ @[eeventname] (Vue)
  • ngModel (NG) / v-model (Vue)

Plus kalau kita lihat di bagian belakangnya(JS dan TS filenya) juga banyak kemiripan strukturnya. Begitu juga dengan approach seperti halnya “two-way data binding” baik di Vue dan NG memiliki cara pakai yang hampir sama(di NG butuh menginclude ngForm di app.module.ts dan elemen yang menggunakannya minimal harus memiliki atribut “id” atau “name”).

Mah sekarang Mari kita bandingkan dengan the old man, jQuery style ….

Kalau kita lihat jQuery HTML-nya akan lebih bersih, tetapi lebih messed di bagian JS. Berbeda dengan framework modern, jQuery tidak meemiliki istilah “data binding.” Sehingga data yang berubah di bagian JS tidak akan langsung mengupdate ke bagian HTML, bahkan untuk mengisi value pada form element, kita harus melakukan query DOM dan menaruhnya manual. Sedangkan both Vue dan NG otomatis melakukan “assign” pada element yang di-bind pada variable di bagian script. Beruntunglah ini sebuah page yang cukup simpel, kalau saja sudah masuk ke halaman yang kompleks, sudah tahu apa jadinya hehehe…