ToDo App lagi, Tapi dengan Livewire

ToDo App lagi, Tapi dengan Livewire

Kembali dari lanjutan kenalan dengan laravel lagi, sebelum masuk ke laravelnya sebenarnya yang membuat saya tertarik banget untuk mencoba lagi laravel adalahh package bernama Livewire. Dari demo yang saya lihat saya langsung suka karena paket ini seperti memberi kemampuan interaktif setara saat menggunakan javascript, bedanya ini “pure” php+html (blade komponen tepatnya).

Agar tidak terlalu kemana-mana tulisan ini dibagi ke dalam dua bagian, pertama sekilas mencoba-coba fitur dasar, dan yang kedua mari buat simple todo app, yah saya gak tahu mau bikin apa dan yang paling gampang ya todo app, jadi tanpa fafifu lebih banyak langsung saja.

Install Livewire

Memasang livewire sama dengan memasang package php pada umumnya dengan composer

composer require livewire/livewire

Gak perlu dulu yang aneh-aneh saya siapkan dulu satu url untuk menjadi playground, buka routes/web.php dan buat seperti berikut

Route::get('demo', function () {
   return view('demo');
});

Lalu di views, buat berkas dengan nama demo.blade.php, isikan standar html template, saya sedikit menambahkan cdn bootstrap aja biar sedikit lebih rapi

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Document</title>
    @livewireStyles()
</head>
<body>
    
    <div class="container">
        <div class="col-12 col-md-10 col-lg-8">
            <div class="card-body row no-gutters align-items-center">
               <h1>Demo Livewire</h1>
            </div>
        </div>
    </div>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    @livewireScripts()
</body>

</html>

Jika diperhatikan di html ada bagian terkait livewire, itu helper untuk load asset yang dibutuhkan agar livewire bisa bekerja.

First Component

Untuk membuat komponen livewire gunakan cli artisan seperti berikut

php artisan make:livewire demo
# demo di sini nama komponen yang saya buat, bisa diganti dengan nama yang dimau

Perintah ini akan membentuk 2 berkas, satu di app/Http/Livewire/Demo.php dan satu lagi di resources/views/livewire/demo.blade.php

Untuk berkas pertama isinya seperti berikut

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Demo extends Component
{
    public function render()
   {
        return view('livewire.demo');
    }
}

 

sedangkan berkas kedua murni html blade biasa

<div>
   // html komponen
</div>

Berkas pertama, class Demo itu bisa dianggap sebagai controller, sehingga semua logic akan bermain di sini, dan yang kedua adalah berkas blade yang nantinya akan berkomunikasi secara langsung dengan class Demo ini.

Model Binding

Tambahkan public properti di berkas Livewire/Demo.php seperti berikut

class Demo extends Component
{
    public $title = 'Demo Livewire';
    public function render()
    {
        return view('livewire.demo');
    }
}

Lalu di komponen blade livewire panggil variable $title

<h1>{{ $title}}</h1>

 

Lalu yang paling menarik adalah ini, bindingnya. Mirip dengan v-model di Vue namun sekali lagi ini “pure” html php, tambahkan textbox di komponen blade tadi menjadi seperti berikut

<div>
<input type="text" class="form-control form-control-lg form-control-borderless" wire:model="title">
<h1>{{ $title}}</h1>
</div>

hasilnya?

Membuat Todo App

Segitu aja dulu, dari sedikit tentang model binding, sekaran mari iseng buat todo app yang menurut saya cukup lumayan dan interaktif walau saya tidak menulis satu baris javascript apapun.

Buat livewire todo dan task, todo sebagai parent dan task sebagai child

php artisan make:livewire todo
php artisan make:livewire task

Seperti biasa, tambahkan saja langsung route baru untuk fokus terkait todo app ini.

Route::get('todo', function () {
  return view('todo');
});

jangan lupa berkas resources/views/todo.blade.php dan isikan seperti berikut

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Document</title>
    @livewireStyles()
</head>
<body>
    
    <div class="container">
        <br/>
        <div class="row justify-content-center">
            @livewire('todo')
        </div>
    </div>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    @livewireScripts()
</body>

</html>

gak pake database-database cukup mainin array, buka berkas livewire/Todo.php buat seperti ini

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Todo extends Component
{
    public $task = '';
    public $tasks = [];

    public function submit()
    {
        array_push($this->tasks, $this->task);
        $this->tasks = $this->tasks;
        $this->task = '';
    }


    public function render()
    {
        return view('livewire.todo');
    }
}

Buka berkas livewire\todo.blade.php, ubah menjadi seperti ini

<div class="col-12 col-md-10 col-lg-8">
    <form class="card card-sm" wire:submit.prevent="submit">
        <div class="card-body row no-gutters align-items-center">
            <div class="col-auto">
                <i class="fas fa-search h4 text-body"></i>
            </div>
            <!--end of col-->
            <div class="col">
                <input wire:model="task" class="form-control form-control-lg form-control-borderless" type="text" placeholder="Add task">
                
            </div>
            <!--end of col-->
            <div class="col-auto">
                <button class="btn btn-lg btn-success">Add</button>
            </div>
            <!--end of col-->
        </div>
    </form>
    <br>
    <div class="row justify-content-center">
        <ul class="list-group">
            @foreach ($tasks as $name)
                @livewire('task', ['task' => $name], key($name))
            @endforeach
        </ul>
    </div>
   
</div>

Sekarang childnya untuk menampung task, ubah livewire\task.blade.php buat seperti ini

@if ($done)
  <li class="list-group-item d-flex justify-content-between align-items-center"><s>{{ $task }}</s></li>
@else
  <li class="list-group-item d-flex justify-content-between align-items-center">{{ $task }} <input type="checkbox" wire:model="done"></li>
@endif

sedangkan pada berkas livewire\Task.php Buat sepert ini untuk menambahkan fungsi menyelesaikan tugas.

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Task extends Component
{
    public $task;
    public $done = false;

    public function render()
    {
        return view('livewire.task');
    }
}

Sehingga hasil akhir seperti berikut

Referensi
https://laravel-livewire.com/docs/2.x/quickstart

Show Comments