Web FullStack menggunakan Phoenix LiveView - Javascript Interoperability
Tags: elixir, phoenixframework, phoenixliveview, jsinterop
Published: 2020-08-16 16:35:53

---
title: Web FullStack menggunakan Phoenix LiveView - Javascript Interoperability
series: Web FullStack menggunakan Phoenix LiveView
---

Bagian ketiga dari *Web FullStack* menggunakan *Phoenix LiveView* akan membahas tentang Javascript Interoperability. Apa itu *Javascript Interoperability* atau lebih dikenal dengan *JS Interop* pada *LiveView* ? Seperti artinya **JS Interop** adalah suatu mekanisme untuk menggunakan kode *Javascript* dalam keseluruhan siklus *LiveView*. Seperti pada tujuan didesain-nya *LiveView* adalah bukan meniadakan fungsi *Javascript* pada kode yang dibangun, tetapi tujuan LiveView adalah meminimalkan penggunaan *Javascript* pada kode *framework Phoenix*. Pada akhirnya cepat atau lambat mekanisme *JS Interop* ini akan digunakan pada kode *framework Phoenix*, karena pada akhirnya kita membutuhkan solusi *custom* ataupun solusi yang lebih *advance* dari *Javascript*, jika kebutuhan dari aplikasi mengharuskan hal tersebut.

Untuk melihat bagaimana penggunaan *JS Interop*, mari kita coba implementasikan fungsi hapus data sebagai bagian dari CRUD dari aplikasi *Todo* yang telah diimplementasikan sebelumnya. Sebelum masuk ke *JS Interop*, akan dibandingkan juga implementasi hapus ini jika **tanpa** menggunakan JS Interop. Seperti biasa, untuk memudahkan dan mempercepat pemahaman, sebelumnya silahkan clone atau fork github repo berikut [https://github.com/rizki96/liveview_todo](https://github.com/rizki96/liveview_todo).

### Solusi penghapusan tanpa **JS Interop**
Solusi tanpa **JS Interop** merupakan solusi yang paling mudah untuk dilakukan. Pertama adalah tambahkan informasi pada file 'lib/liveview_todo_web/router.ex', sehingga terdapat link untuk melakukan penghapusan atau *delete* pada **endpoint** '/todo'. Berikut contoh penggalan kode dari router.ex

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=router.ex-1 %}

Saat ini artinya module TodoLive telah memiliki endpoint :delete. Sehingga file 'lib/liveview_todo_web/live/components/todos/todo_list_item.ex' dapat ditambahkan salah satu fungsi link html untuk liveview yaitu *live_redirect* untuk melakukan operasi penghapusan. Berikut isi file 'todo_list_item.ex' yang terbaru

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_list_item.ex-1 %}

Terlihat dari fungsi *live_redirect*, link tersebut akan membawa menuju ke *Routes.live_path(@socket, TodoLive, [id: @todo.id, action: :delete]), replace: false)*, Routes.live_path ini merupakan representasi dari link '/todo' yang ada pada file 'router.ex', yang kemudian akan di render oleh browser sebagai '/todo?id={id}&action=delete'. Dan dari router live_path tersebut, client akan dibawa ke fungsi *handle_params* pada module *TodoLive*. Seterusnya module *TodoLive* akan berbentuk sebagai berikut 

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_live.ex-1 %}

Maka setelah semua kode tersebut terpasang, maka penghapusan sudah bisa dilakukan. Tetapi ada hal yang perlu diingat dari kode diatas. Yaitu jika dilihat pada bagian '# versi tanpa *JS Interop*' setelah *handle_params* melakukan penghapusan terhadap data *todo*, maka semua data kembali akan di *fetch* dari database dengan fungsi *{:ok, todos} = Tasks.list_todos()* dan *state* dari todos akan di *assign* ulang. Hal ini tentu akan menimbulkan *bottle neck* jika jumlah data todo yang di *fetch* cukup signifikan. Untuk menghindari hal tersebut, yang perlu dilakukan adalah mengganti operasi fetch data tadi dengan operasi pengiriman event ke client browser dalam hal ini ke Javascript, sehingga nanti Javascript yang akan melakukan penghapusan todo item, tanpa perlu melakukan fetch data dan mengirimkan data ke client browser. Hal tersebut akan coba dijelaskan pada bagian berikutnya yaitu solusi menggunakan *JS Interop*. Dan berikut adalah ilustrasi pengiriman data dari server ke client dengan solusi **tanpa** *JS Interop*.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/2k5tfpcvm4ygiyzfbf29.png" width="500" alt="ilustrasi pengiriman data yang difetch dari database dengan solusi tanpa JS Interop" />

### Solusi penghapusan dengan **JS Interop**
Sebelumnya perlu diketahui bahwa *JS Interop* merupakan sebuah siklus berupa fungsi callback yang terjadi pada sebuah *LiveView Component*. Siklus tersebut terdiri dari fungsi mounted, beforeUpdate, updated, beforeDestroy, destroyed dan lainnya, untuk lebih jelas tentang siklusnya bisa dilihat pada [link ini](https://hexdocs.pm/phoenix_live_view/js-interop.html).

Disebabkan karena yang akan melakukan penghapusan ada pada elemen list, maka akan diimplementasikan *JS Interop* ini pada *LiveView Component* 'todo_list.ex' pada direktori 'lib/liveview_todo_web/live/components/todos'. Untuk memulai mari buat sebuah file javascript yang berfungsi sebagai hook, pada direktori 'assets/js' dengan nama file 'todo_list_hook.js'. Berikut isi dari file 'todo_list_hook.js'

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_list_hook.js-1 %}

Kemudian lakukan modifikasi pada file 'app.js' pada direktori 'assets/js', dimana file Javascript ini yang akan dimuat (*load*) untuk pertama kali pada client browser. Berikut isi dari file 'app.js'

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=app.js-1 %}

Dari kode diatas terlihat object hook TodoListHook di-import dan kemudian diteruskan ke dalam object LiveSocket. Setelah ini dibutuhkan melakukan modifikasi file berturut-turut yaitu 'todo_list.ex', 'todo_list_item.ex' dan 'todo_live.ex'. Pada file 'todo_list.ex' yang akan ditambahkan adalah tag phx-hook dengan nilai 'TodoListHook' (phx-hook='TodoListHook'). Sehingga isi file 'todo_list.ex' akan berbentuk

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_list.ex-1 %}

Pada file 'todo_list_item.ex' akan diubah fungsi 'live_redirect' menjadi 'live_patch'. Perbedaan 'live_redirect' dan 'live_patch' adalah pada 'live_redirect', phoenix yang akan menangani redirecting / pengarahan ke konten liveview yang baru dengan assign state yang baru. Pada 'live_patch' hal tersebut tidak dilakukan, semua operasi tersebut akan ditangani oleh Javascript. 'live_patch' hanya akan mengirimkan event ke *handle_params*. Berikut isi dari file 'todo_list_item.ex'

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_list_item.ex-2 %}

Bagaimana file 'todo_live.ex' ? Bagian yang dibutuhkan untuk dimodifikasi adalah bagian *handle_params*. Berikut isi dari file 'todo_live.ex' setelah dimodifikasi

{% gist https://gist.github.com/rizki96/b72755b702a0b092e3a4bace794cbb91 file=todo_live.ex-2 %}

Seperti bisa dilihat pada kode diatas, setelah penghapusan data operasi yang dilakukan adalah pengiriman event oleh fungsi 'push_event'. Event ini akan ditangkap oleh 'TodoListHook' pada file 'assets/js/todo_list_hook.js' di bagian 'this.handleEvent' yang kemudian akan menghapus element data todo yang bersangkutan pada *LiveView Component* 'todo_list.ex'. Sebagai bahan perbandingan, berikut informasi yang dikirim dari server ke client browser, jika menggunakan *JS Interop*. Data yang dikirim hanya informasi event dan todo data dari object yang telah dihapus di server. Dan terlihat dengan *JS Interop* ini akan mengefisienkan pengiriman data dari server ke client browser.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/20ipjgrgn3reew1vv5qf.png" width="500" alt="ilustrasi pengiriman data dengan menggunakan solusi JS Interop" />

Dan terakhir, perlu diketahui bahwa dengan JS Interop ini dimungkinkan untuk LiveView berinteraksi dengan framework Javascript lain, seperti JQuery, React, Vue.js dan lain sebagainya. Demikian sekilas mengenai JS Interop pada Phoenix LiveView, mudah-mudahan bisa bermanfaat. Terima kasih.