ساخت یک کامپوننت Todo با Livewire با نکات مفید

همانطور که در مقاله قبل (فول استک کار کردن با Laravel Livewire) در مورد livewire توضیح دادم و هچنین روش ایجاد یک کامپوننت رو نشون دادم٬ در این مقاله توضیحات بیشتری به همراه قابلیت های دیگر در مورد این پکیج قرار میدم. چون در عمل و تمرین مطلب رو بهتر درک میکنیم.قدم اول٬ با استفاده از دستور زیر یک کلاس یا کامپوننت جدید از livewire ایجاد میکنیم.php artisan livewire:make Todoما یک فرم به صورت عکس زیر درست کردیم و همچنین در انتهای فرم لیست Todo های اضافه شده رو نشون میدیم.کد نویسی در کامپوننت ایجاد شده از Livewireاز اونجایی که ما در حال حاضر نمیخوایم با دیتابیس کار کنیم٬ یک آرایه ایجاد میکنیم که لیست Todo ها رو نشون بدیم. (البته به همین روش میتونیم به راحتی به دیتابیس وصل شد!)ما مقادیری که نیاز داریم در لایه نمایشی (در فایل Blade) باهاشون کار کنیم٬ طبق روش زیر به کلاس کامپوننت اضافه میکنیم:/** * Title in form * @var string */ public $title; /** * Content or Desc in form * @var strnig */ public $content; /** * List of Items * @var array */ public $list; با استفاده از متد mount میتونیم به پارامتر list مقدار بدیم (اگر با VueJs آشنایی داشته باشید٬ این متد دقیقا کار متد mount در این کتابخانه از جاوااسکریپت رو انجام میده) این متد زمانی که کلاس برای اولین بار در یک صفحه لود میشه٬ اجرا میشه! /** * Mount component (Like VueJs Mount) */ public function mount() { $this->list = collect(); }به این پارامتر یک Collection پاس میدیم که قابلیت بیشتری برای کار با آرایه ها داشته باشیم.برای دریافت مقادیر از فرم و اضافه کردن به لیست Todo ها یک متد Submit ایجاد میکنیم./** * Submit form */ public function submit() { $this->list->push([ 'id' => Str::uuid(), 'title' => $this->title, 'content' => $this->content, ]); $this->emit('removeFormFields'); }پارامترهای title و content رو از فرم دریافت میکنیم و به لیست اضافه میکنیم. بعد از اضافه شدن آیتم٬ یک متد emit صدا زده شده٬ کار این متد اجرا کردن یک متد تعریف شده در کلاس مربوطه یا در کلاس/کامپوننت های اجرا شده در همان صفحه وب جاری است!protected $listeners = [ 'removeFormFields' ];زمانی که برای یک event متد (function) تعریف میکنیم٬ پارامتر بالا رو نیازه به کلاس کامپوننت اضافه کنیم تا متد تعریف شده شناسائی بشه.حتی با استفاده از متد emit میتونیم یک event در سمت جاوااسکریپت اجرا کنیم و عملیات مورد نظر خودمون رو انجام بدیم. یک نمونه در همین مثال آماده کردم که در ادامه نشون میدم.در این بخش ما متد removeFormFields رو در کلاس Todo خودمون ایجاد کردیم که بگیم بعد از ایجاد٬ مقادیر title و content رو null یا خالی کن٬ این کار در فرم html ما عمل میکنه و مقادیر وارد شده را بعد از ایجاد حذف میکنه./** * Remove Form Fields and trigger todoIsAdded Event */ public function removeFormFields() { $this->title = null; $this->content = null; $this->emit('todoIsAdded'); }همانطور که در کد بالا نشون داده٬ بعد از خالی کردن مقادیر٬ یک event به اسم todoIsAdded صدا زده شده٬ اما برای این یک نوع٬ هیچ متد ی در کلاس ننوشتم و در Javascript به عنوان یک Listener گرفته و عملیات انجام میدم.@livewireScripts .... window.livewire.on('todoIsAdded', function (){ alert('The ToDo item is added!') }); کد بالا (یک alert رو اجرا میکنه) زمانی اجرا میشه که event todoIsAdded صدا زده بشه! به همین صورت ما میتونیم به تعداد دلخواه در یک صفحه event تعریف کنیم و به کامپوننت های مختلف دسترسی داشته باشیم. همچنین حتی میتونیم به کامپوننت های مختلف با استفاده از متد emit مقادیری رو پاس بدیم!در نهایت یک متد Remove هم تعریف میکنم که Todo ها رو پاک کنیم./** * Remove item * @param $id */ public function remove($id) { $this->list = $this->list->reject(function ($item) use ($id) { return $item['id'] == $id; }); }HTML<div class=&quotlg:px-8&quot> <form wire:submit.prevent=&quotsubmit&quot> <div class=&quotcol-md-4&quot> <div class=&quotform-group&quot> <label for=&quottitle&quot>Title:</label> <input type=&quottext&quot placeholder=&quotTitle&quot wire:model.lazy=&quottitle&quot class=&quotform-control&quot> </div> </div> <div class=&quotcol-md-4&quot> <div class=&quotform-group&quot> <label for=&quottitle&quot>Desc:</label> <textarea type=&quottext&quot placeholder=&quotDesc&quot wire:model.lazy=&quotcontent&quot class=&quotform-control&quot></textarea> </div> </div> <div class=&quotbtn-group&quot style=&quotmargin-top: 10px&quot> <label for=&quot&quot></label> <button class=&quotbtn btn-primary&quot>Submit</button> </div> </form> </div> <hr> <div class=&quotcol-md-6&quot> Show List: @if(!$list->count()) <p>There is no result.</p> @endempty <ol class=&quotlist-group list-group-numbered&quot> @foreach($list as $item) <li class=&quotlist-group-item d-flex justify-content-between align-items-start @if(($loop->index + 1) % 2 == 0) list-group-item-primary @endif&quot> <div class=&quotms-2 me-auto&quot> <div class=&quotfw-bold&quot>{{$item['title']}}</div> {{$item['content']}} </div> <span class=&quotbtn btn-danger btn-sm&quot wire:click=&quotremove('{{$item['id']}}')&quot>Remove</span> </li> @endforeach </ol> </div>PHP<?php namespace App\Http\Livewire; use Illuminate\Support\Str; use Livewire\Component; class Todo extends Component { protected $listeners = [ 'removeFormFields' ]; /** * Title in form * @var string */ public $title; /** * Content or Desc in form * @var string */ public $content; /** * List of Items * @var array */ public $list; /** * Mount component (Like VueJs Mount) */ public function mount() { $this->list = collect(); } /** * Submit form */ public function submit() { $this->list->push([ 'id' => Str::uuid(), 'title' => $this->title, 'content' => $this->content, ]); $this->emit('removeFormFields'); } /** * Remove Form Fields and trigger todoIsAdded Event */ public function removeFormFields() { $this->title = null; $this->content = null; $this->emit('todoIsAdded'); } /** * Remove item * @param $id */ public function remove($id) { $this->list = $this->list->reject(function ($item) use ($id) { return $item['id'] == $id; }); } /** * Render component view * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View */ public function render() { return view('livewire.todo'); } }با استفاده از ویژگی های livewire کارهای بسیاری رو میتونیم بدون نوشتن کد در جاوااسکریپت انجام بدیم و برنامه های خودمون رو پویا سازی کنیم.امیدوارم مطالب مفید باشه٬ آرزوی سلامتی و موفقیت دارم.