Laravel ကို ဘယ် Front-end နည်းပညာနဲ့မဆို တွဲဖက်အသုံးပြုလို့ရပါတယ်။ အဲ့ဒီလို တွဲဖက်အသုံးပြုလို့ရတဲ့ နည်းပညာတွေထဲက Livewire အကြောင်းကို တစ်ခါထဲ လက်တွေ့လိုက်လုပ်ကြည့်လို့ရမယ့် Tutorial ပုံစံနဲ့ ပြီးခဲ့တဲ့ ပိုစ့်မှာ ဖော်ပြခဲ့ပြီးဖြစ်ပါတယ်။
အဲ့ဒီ Tutorial မှာ Class Component တွေကို အသုံးပြု ဖော်ပြခဲ့ပြီး ဒီတစ်ခါတော့၊ ပုံစံတူ Tutorial ကိုပဲ အသစ်ထွက်ထားတဲ့ Livewire 3 မှာပါတဲ့ Functional Component တွေနဲ့ အနည်းငယ်ပြင်ဆင်ပြီး ထပ်မံဖော်ပြလိုက်ပါတယ်။
စမ်းသပ်ကြည့်နိုင်ဖို့အတွက် ပထမဆုံး Laravel ပရောဂျက် အသစ်တစ်ခုကို အခုလို တည်ဆောက်ယူလိုက်ပါ။
composer create-project laravel/laravel laravolt
နမူနာအရ laravolt
ဆိုတဲ့ ဖိုဒါအမည်နဲ့ Laravel ပရောဂျက်သစ်တစ်ခု ရရှိသွားပါလိမ့်မယ်။ ပရောဂျက်ဖိုဒါထဲကို cd laravolt
နဲ့ဝင်ပြီး Laravel Breeze ကို အခုလို Install လုပ်လိုက်ပါ။
composer require laravel/breeze --dev
Laravel Breeze ဟာ အသင့်သုံး User Authentication System ကို Tailwind တို့ Livewire တို့နဲ့ ရေးပေးထားတဲ့ Official Package တစ်ခုဖြစ်ပါတယ်။ ဒီ Package ကို Install လုပ်လိုက်ခြင်းအားဖြင့် User Authentication အပြင် Tailwind တို့ Livewire တို့လည်း တစ်ခါထဲ ထည့်သွင်းပါဝင်သွားပြီး ဖြစ်စေပါတယ်။ ကိုယ့်ဘာသာ တစ်ခုချင်း ထပ်ထည့်စရာ မလိုတော့ပါဘူး။
ပြီးခဲ့တဲ့ပိုစ့်ကို ရေးနေစဉ်အချိန်ထိ Laravel Breeze ကို Livewire Class Component တွေနဲ့ ဖန်တီးထားခြင်းဖြစ်ပြီး၊ သိပ်မကြာသေးခင်ကပဲ Functional Component တွေနဲ့ ပြင်ရေးပေးထားတဲ့ Update ကို ထုတ်ပေးလိုက်ပါပြီ။ ဒါကြောင့် အခုနေ Install လုပ်လိုက်ရင် ရရှိမယ့် Updated Laravel Breeze က Functional Component တွေနဲ့ ဖြစ်နေပြီး ဖြစ်ပါလိမ့်မယ်။
ပြီးတဲ့အခါ လိုအပ်တဲ့ Setup တွေ ပြုလုပ်စေဖို့အတွက် ဒီ Command ကို Run ပေးပါ။
php artisan breeze:install
လာမေးတဲ့ မေးခွန်းတွေထဲက Livewire (Volt Functional API) with Alpine
ကို ရွေးပေးပါ။ ဒါဆိုရင် Livewire Functional Component တွေကို အသုံးပြုပြီး လိုအပ်တဲ့ Setup တွေကို သူက လုပ်ပေးသွားမှာပါ။ ကျန်မေးခွန်းတွေကိုတော့ အခုထည့်ကြည့်မယ့်ထဲမှာ မပါသေးလို့ နှစ်သက်ရာသာ ရွေးလိုက်ပါ၊ ရပါတယ်။
ဆက်လက်ပြီး စမ်းကြည့်စရာ Data ရအောင် Migrate တွေ Seed တွေ လုပ်ကြပါမယ်။ အရင်ဆုံး .env
ဖိုင်မှာ DB_DATABASE=laravel
ကို DB_DATABASE=laravolt
လို့ ပြင်ပေးပြီး migrate Run ပေးလိုက်ပါ။
php artisan migrate
Migration Run စဉ်မှာ Database မရှိသေးလို့ ဆောက်မှာလားမေးရင် Yes
ကို ရွေးပေးပါ။ ပြီးတဲ့အခါ Sample Data လေးတစ်ချို့ ထည့်ဖို့အတွက် database/seeders/DatabaseSeeder.php
မှာ Comment ပိတ်ထားတဲ့ ဒီလိုင်းလေးကို ဖွင့်ပေးလိုက်ပါ။
\App\Models\User::factory(10)->create();
Seed Run ပြီး Sample Data ထည့် လို့ရပါပြီ။
php artisan db:seed
Server တွေ Run ဖို့ရယ်၊ လိုအပ်တဲ့ Command Run ဖို့ရယ် Terminal (၃) ခုလိုပါမယ်။ Server တွေကို Background Service အနေနဲ့ Run ပြီး Manage လုပ်တတ်ရင်တော့ တစ်ခုထဲလည်း ရပါတယ်။ ဒါပေမယ့် ဒီနေရာမှာတော့ ရှင်းသွားအောင် (၃) ခုခွဲသုံးတယ်လို့သာ သဘောထားပါ။ အရင်ဆုံး Terminal တစ်ခုမှာ Client-side Dev Server ကို အခုလို Run လိုက်ပါ။
npm run dev
Run လက်စကို ပိတ်လိုက်လို့ မရပါဘူး။ ဒီအတိုင်း Run ထားရမှာပါ။ Terminal နောက်တစ်ခုနဲ့ PHP Dev Server ကို အခုလို Run လိုက်ပါ။
php artisan serve
သူလည်း Run လက်စကို ပိတ်လိုက်လို့ မရပါဘူး။ ဒီအတိုင်း ဆက် Run ထားရမှာပါ။ Browser မှာ localhost:8000 နဲ့ စမ်းကြည့်လို့ရပါပြီ။
ဆက်လက်ပြီး နောက် Terminal တစ်ခုမှာ အခုလို Run ပြီး လိုအပ်တဲ့ Livewire Component တွေ View တွေဖန်တီးလိုက်ပါ။
php artisan livewire:layout
php artisan make:volt users/user-list
php artisan make:volt users/user-detail
php artisan make:volt users/user-add
ပထမ Command က resources/views/components/layouts/app.blade.php
အမည်နဲ့ Main Layout View ဖိုင်တစ်ခုကို တည်ဆောက်ပေးသွားမှာဖြစ်ပါတယ်။ Livewire Functional Component တွေအတွက် make:livewire
မဟုတ်ဘဲ make:volt
ကိုသုံးထားတာ သတိပြုပါ။ Class ဖိုင်တွေ မလိုအပ်တော့ဘဲ View ဖိုင်တွေကိုတော့ resources/views/livewire
ထဲမှာ တည်ဆောက်ပေးသွားမှာ ဖြစ်ပါတယ်။ ဒါကြောင့် make:volt
Command (၃) ခုကနေ ရရှိလာမယ့် ဖိုင်တွေက ဒီလိုပါ
resources/views/livewire/users/user-list.blade.php
resources/views/livewire/users/user-detail.blade.php
resources/views/livewire/users/user-add.blade.php
resources/views/components/layouts/app.blade.php
ထဲက ကုဒ်ကို အခုလိုပြင်ပေးလိုက်ပါ။
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Livewire</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<div class="min-h-screen bg-gray-100">
<header class="bg-white shadow">
<div class="flex max-w-5xl mx-auto py-6 px-4">
<h2 class="font-semibold text-xl
text-gray-800 leading-tight">
Livewire
</h2>
<a class="text-green-600 ms-6"
href="/users/add" wire:navigate>+ Add User</a>
</div>
</header>
<main class="max-w-3xl mx-auto py-6 px-4">
{{ $slot }}
</main>
</div>
</body>
</html>
ဒီဖိုင်က Livewire Component တွေကို Full Page Component အနေနဲ့ ပြတဲ့အခါ Main Template အဖြစ် အသုံးပြုပေးမယ့်ဖိုင် ဖြစ်ပါတယ်။ အဓိကထူးခြားချက် နှစ်ချက်ပဲပါပါတယ်။ $slot
နေရာမှာ Component ကို လာပြမှာဖြစ်ပြီး၊ <a>
Element မှာ wire:navigate
Attribute ပါသွားပါတယ်။ ဒါကြောင့် ဒီ <a>
Element ကို နှိပ်တဲ့အခါ နောက်တစ်မျက်နှာအနေနဲ့ Page Reload နဲ့ မသွားတော့ဘဲ သက်ဆိုင်ရာ Component ကို နေရာမှာတင် Single-page အနေနဲ့ ပြောင်းပြီး ပြပေးသွားမှာပါ။ JavaScript တွေမလိုဘဲ PHP နဲ့ပဲ Single-page အလုပ်လုပ်အောင် ရေးလို့ရသွားခြင်းပဲ ဖြစ်ပါတယ်။
ပြီးတဲ့အခါ resources/views/livewire/users/user-list.blade.php
မှာ အခုလို ရေးပေးလိုက်ပါ။
<?php
use App\Models\User;
use function Livewire\Volt\state;
state([ 'users' => fn () => User::all() ]);
$delete = function ($id) {
$user = User::find($id);
$user->delete();
$this->users = User::all();
}; ?>
<ul class="mt-4">
@foreach ($users as $user)
<li class="border-b py-2 mb-2 flex justify-between"
wire:key="{{ $user->id }}">
<a href="/users/view/{{ $user->id }}"
class="text-blue-700" wire:navigate>
{{ $user->name }}
</a>
<button wire:click="delete({{ $user->id }})"
class="text-red-500 text-xl font-bold">
×
</button>
</li>
@endforeach
</ul>
Volt ရဲ့ state()
Function ကို သုံးပြီး $users
State ကြေညာထားပါတယ်။ User
Model ရဲ့အကူအညီနဲ့ လက်ရှိနမူနာ User Data တွေ ထည့်ပေးထားပါတယ်။ ပြီးတဲ့အခါ $delete
အတွက် Anonymous Function တစ်ခုရေးထည့်ပေးထားပြီး ပေးလာတဲ့ $id
နဲ့ကိုက်ညီတဲ့ User ကို ဖျက်ထားပါတယ်။ ဖျက်ပြီးတဲ့အခါ $this->users
နဲ့ State ကို Update လုပ်ပေးလိုက်ပါတယ်။
ဆက်လက်ရေးသားထားတဲ့ Template ကတော့ သိပ်ရှုပ်ရှုပ်ယှက်ယှက် မဟုတ်ပါဘူး။ $users
State Data ကို Loop လုပ်ပြီး ပြထားလိုက်တာပါပဲ။ ကြည့်ကောင်းအောင် Tailwind Class တွေသုံးထားပေမယ့် အဓိကပိုကျတာက wire:key
wire:navigate
wire:click
ဆိုတဲ့ Attribute တွေပါ။
wire:key
ရဲ့ သဘောကိုတော့ React တို့ Vue တို့ လေ့လာဖူးသူတွေ သိကြပါလိမ့်မယ်။ Loop လုပ်ထားတဲ့ Item တွေမှာ Unique ဖြစ်တဲ့ Key Attribute ရှိမှသာ နောက်ပိုင်း အပြောင်းအလဲ ရှိတဲ့အခါ List တစ်ခုလုံးကို အစအဆုံး ပြန်ပြီး Render လုပ်စရာမလိုဘဲ လိုတဲ့အပိုင်းလေးပဲ ရွေးပြီး လုပ်လို့ရစေဖို့ ဖြစ်ပါတယ်။
wire:navigate
ရဲ့သဘော အကျဉ်းချုပ်ကို အပေါ်မှာ ပြောခဲ့ပြီးပါပြီ။ wire:click
ကတော့ Button ကို နှိပ်တဲ့အချိန်မှာ Run စေချင်တဲ့ Function ကို ပေးရတာပါ။ ဒါကြောင့် delete
ကို ပေးထားပါတယ်။ ပုံမှန်အားဖြင့် Button Click မှာ PHP ကုဒ်တွေ Run လို့မရပါဘူး။ Client-side, Server-side တူမှ မတူတာကိုး။ Run ချင်ရင် JavaScript ကုဒ်တွေဘဲ Run လို့ရမှာပါ။ Livewire က wire:click
နဲ့ Button Click မှာ PHP ကုဒ်တွေ Run လို့ရအောင် လုပ်ပေးလိုက်တာပါ။
ဆက်လက်ပြီး စတင်စမ်းသပ်နိုင်ဖို့အတွက် routes/web.php
မှာ အခုလို Volt ကို Import လုပ်ပြီး Route တစ်ချို့ ရေးထည့်ပေးလိုက်ပါ။
use Livewire\Volt\Volt;
Volt::route('/users', 'users.user-list');
Volt::route('/users/view/{id}','users.user-detail');
Volt::route('/users/add', 'users.user-add');
ပုံမှန်အားဖြင့် Route
Facade ကိုသုံးပြီး Controller တွေ View တွေကို လှမ်းချိတ်မှာပါ။ အခုတော့ Route
ကိုမသုံးတော့ဘဲ Volt
ကို ပြောင်းသုံးထားပါတယ်။ Volt
ရဲ့ route()
မှာ ရှေ့က URI လိပ်စာနဲ့ နောက်က ဖော်ပြရမယ့် Component ကို ပေးလိုက်တာပါ။ ဒါကြောင့် /users
Route ကို သွားလိုက်ရင် users/user-list
Component ကို Layout ထဲမှာ ထည့်ပြီး Full-page Component အနေနဲ့ ပြပေးလာမှာ ဖြစ်ပါတယ်။
ကျန်တဲ့ user-detail
တွေ user-add
တွေ ထပ်မရေးခင် ဒီအဆင့်မှာတင် စတင်စမ်းသပ်ကြည့်လို့ရပါပြီ။
localhost:8000/users ကိုသွားကြည့်လိုက်ရင် အခုလိုရလဒ်ကို ရရှိမှာဖြစ်ပါတယ်။ Database Table ထဲက Users တွေကို users/user-list
Component နဲ့ လာပြပေးနေခြင်းပဲ ဖြစ်ပါတယ်။
Delete လုပ်ဆောင်ချက်ကို တစ်ခါထဲ စမ်းကြည့်လို့ရပါတယ်။ React တို့ဘာတို့မှာ State ပြောင်းရင် Component လိုက်ပြောင်းပေးနိုင်သလိုပဲ လက်ရှိရေးထားတဲ့ delete
Function အရ Server-side ဘက်မှာ Data ပျက်သွားယုံသာမက State ကိုလည်း တစ်ခါထဲ Update လုပ်ပေးထားတဲ့အတွက် Client-side List ကလည်း Page Refresh တွေဘာတွေ မလိုဘဲ အလိုအလျှောက် Update ဖြစ်သွားမှာ ဖြစ်ပါတယ်။
ဆက်လက်ပြီး resources/views/livewire/users/user-detail.blade.php
မှာ အခုလိုရေးပေးပါ။
<?php
use App\Models\User;
use function Livewire\Volt\state;
use function Livewire\Volt\mount;
state([ 'user' => null ]);
mount(function($id) {
$this->user = User::find($id);
}); ?>
<div class="border rounded p-4">
<h3 class="text-2xl mb-2">{{ $user->name }}</h3>
<p class="text-gray-600 mb-2">{{ $user->email }}</p>
<div class="mb-4">
<small class="text-gray-400">
{{ $user->created_at->diffForHumans() }}
</small>
</div>
<a href="/users" class="text-blue-500"
wire:navigate>« Go back</a>
</div>
ပထမဆုံး $user
State ကြေညာထားပါတယ်။ ပြီးတဲ့အခါ mount()
Function ကို သုံးပြီး User
Model ရဲ့ အကူအညီနဲ့ User Data တွေထုတ်ယူထားပါတယ်။ ရလာတဲ့ Data တွေကို $user
State ထဲမှာ ထည့်ပေးလိုက်တာပါ။
ဒီနေရာမှာ mount()
Function ကို အသုံးပြုရတာက $id
URL Parameter ကို လိုချင်လို့ပါ။ Route မှာ /users/view/{id}
လို့ သတ်မှတ်ထားတဲ့အတွက် Controller Method တွေမှာ $id
ကို ယူသုံးလို့ရသလိုပဲ mount()
မှာလည်း ယူသုံးလို့ရပါတယ်။ mount()
Function ဟာ Livewire ရဲ့ Lifecycle Function တွေထဲကတစ်ခုဖြစ်ပြီး Component ကို Render လုပ်တဲ့အချိန်တိုင်းမှာ အလိုအလျှောက် အလုပ်လုပ်တဲ့ Function တစ်ခုပါ။
ဆက်ရေးထားတဲ့ Template ကုဒ်မှာ wire:navigate
နဲ့ Link တစ်ခုပါပေမယ့် အခြေခံအားဖြင့် $user
Data တွေကို Box လေးတစ်ခုနဲ့ ပြလိုက်တာပါပဲ။
ဒီလောက်ဆိုရင် User View လည်းရသွားပါပြီ။ List ထဲက User တစ်ယောက်ကို နှိပ်လိုက်ရင် Page Reload မလိုအပ်ဘဲ user-detail
Component ကို ပြပေးသွားမှာဖြစ်သလို၊ user-detail
က Go Back Link ကို နှိပ်လိုက်ရင်လည်း Page Reload မလိုဘဲ user-list
ကို ပြန်ပြပေးသွားပါလိမ့်မယ်။
User တွေအသစ်ထပ်ထည့်ဖို့အတွက် Form Template တစ်ခုလိုပါမယ်။ resources/views/livewire/users/user-add.blade.php
မှာ အခုလိုရေးပေးပါ။
<?php
use App\Models\User;
use function Livewire\Volt\state;
use function Livewire\Volt\rules;
state([ 'name' => '', 'email' => '' ]);
rules([
'name' => ['required'],
'email' => ['required', 'email'],
]);
$save = function () {
$this->validate();
User::factory()->create([
"name" => $this->name,
"email" => $this->email,
]);
$this->redirect("/users", navigate: true);
}; ?>
<form wire:submit="save">
<input type="text" wire:model="name"
class="w-full border rounded p-3"
placeholder="Name">
<div class="text-red-600 text-sm mb-3">
@error('name') {{ $message }} @enderror
</div>
<input type="text" wire:model="email"
class="w-full border rounded p-3"
placeholder="Email">
<div class="text-red-600 text-sm mb-3">
@error('email') {{ $message }} @enderror
</div>
<button type="submit"
class="rounded bg-blue-700 text-white py-2 px-6">
Add User
</button>
</form>
$name
နဲ့ $email
State နှစ်ခု ကြေညာထားပါတယ်။ ပြီးတဲ့အခါ rules()
Function ရဲ့ အကူအညီနဲ့ Validation Rules တွေသတ်မှတ်ထားပါတယ်။ ဒါကြောင့် $save
Function မှာ $this->validate()
ကိုခေါ်လိုက်တဲ့အခါ State Data တွေဟာ သတ်မှတ်ထားတဲ့ Rule များအတိုင်း ကိုက်ညီမှုရှိမရှိ Validation စစ်ပြီး Fails ဖြစ်ခဲ့ရင် ဆက်မလုပ်ဘဲ Validation Error တွေနဲ့ Component ကို ပြန်ပြပေးမှာ ဖြစ်ပါတယ်။
အောက်က Template ကုဒ်ထဲမှာ Blade @error
Directive နဲ့ Validation Error ရှိမရှိစစ်ပြီး ရှိရင် တစ်ခါထဲ ပြခိုင်းထားပါတယ်။ State Data တွေဖြစ်ကြတဲ့ name
တို့ email
တို့ကို ဆက်လက်ရေးသားထားတဲ့ Template ရဲ့ Input တွေမှာ wire:model
နဲ့ ချိတ်ပေးထားတာကိုလည်း သတိပြုကြည့်ပါ။
Validation Pass ဖြစ်ခဲ့ရင်တော့ User
Model ရဲ့ Factory အကူအညီနဲ့ User အသစ် Create လုပ်လိုက်ပါတယ်။ Factory ကိုသုံးရတာက User အတွက် Password အပါအဝင် တစ်ခြားလိုအပ်တာတွေ ထည့်မပေးလိုတဲ့အတွက် ပေးချင်တဲ့ Name နဲ့ Email ကိုပဲ ပေးပြီး ကျန် Value တွေကို Factory မှာ သတ်မှတ်ထားတဲ့အတိုင်း ထည့်ပေးလိုက်စေချင်လို့ပါ။
နောက်ဆုံးမှာ လုပ်စရာရှိတာတွေလုပ်ပြီးရင် $this->redirect()
နဲ့ /users
Route ကို ပြန်သွားခိုင်းတဲ့အခါ navigate: true
Parameter ထည့်ပေးထားပါတယ်။ ဒါကြောင့် ထုံးစံအတိုင်း Livewire က Page Reload ပြန်မလုပ်တော့ဘဲ /users
Route နဲ့ ချိတ်ထားတဲ့ user-list
Component ကို ပြန်ပြပေးသွားမှာပဲ ဖြစ်ပါတယ်။
ဆက်ရေးထားတဲ့ Template ကတော့ name
နဲ့ email
ကို Input နှစ်ခုနဲ့ တောင်းထားတဲ့ HTML Form တစ်ခုသာဖြစ်ပါတယ်။ အရေးအကြီးဆုံး ထူးခြားချက်ကတော့ <form>
မှာ wire:submit
နဲ့ save
ကို ခေါ်ထားခြင်းဖြစ်ပါတယ်။ ဒါကြောင့် ဒီ Form မှာ Submit နှိပ်လိုက်ရင် Page Reload နဲ့ Server Submit မလုပ်တော့ဘဲ $save
Function ကို ခေါ်ပေးသွားမှာဖြစ်ပါတယ်။
နောက်ထပ်အရေးကြီးတာကတော့ Input တွေမှာပါတဲ့ wire:model
ဖြစ်ပါတယ်။ လိုရင်းကတော့ Input ကို State နဲ့ ချိတ်ပေးလိုက်တာပါ။ ဒါကြောင့် ဒီ Input တွေမှာ ရေးဖြည့်လိုက်သမျှ သက်ဆိုင်ရာ name
နဲ့ email
State တွေထဲကို အလိုအလျှောက် ရောက်သွားမှာပါ။
User အသစ်တွေ ထည့်ပြီး စမ်းကြည့်လို့ရပါပြီ။
ဒီလောက်ဆိုရင် Livewire Functional Component တွေရဲ့ အလုပ်လုပ်ပုံကို တော်တော်လေး သဘောပေါက်သွားလောက်ပြီလို့ ယူဆပါတယ်။ အလားတူလုပ်ဆောင်ချက်မျိုးရဖို့အတွက် JavaScript Framework တစ်ခုခုကိုသုံးပြီး ရေးရင်လည်း ရနိုင်ပေမယ့်၊ ဒီနည်းကြောင့် Back-end သပ်သပ် Front-end သပ်သပ် ခွဲပြီး Maintain လုပ်စရာမလိုတော့သလို API Call တွေကိုလည်း Management လုပ်စရာမလိုတော့ပါဘူး။ တစ်ချို့က သပ်သပ်စီ ခွဲရေးရတာကို နှစ်သက်နိုင်ပေမယ့်၊ အခုလို Language တစ်မျိုးထဲနဲ့ Laravel Framework ထဲကနေ ထွက်စရာမလိုဘဲ စီမံရေးသားနိုင်ခြင်းဟာလည်း အသုံးဝင်တဲ့ နည်းပညာတစ်ခုပဲ ဖြစ်ပါတယ်။
နိဂုံးချုပ်အနေနဲ့ သတိပြုစေချင်တဲ့ အချက်ကတော့ လက်ရှိနမူနာကုဒ်မှာ M-V-C ရဲ့ C (ခေါ်) Controller လုံးဝ ပြုတ်သွားခြင်းပါပဲ။ Controller ကုဒ်တွေ ရေးရိုးရေးစဉ်အတိုင်း ဆက်ရေးလို့လည်း ရပါတယ်။ API ကုဒ်တွေပါမယ်ဆို မဖြစ်မနေ ထည့်ရေးရမှာပါ။ ဒါပေမယ့် M-V-C ဟာ အစဉ်အလာ Server-side Request/Response Cycle တွေပေါ်အခြေခံတဲ့ App နဲ့သာ အထူးသင့်တာဖြစ်လို့၊ အခုလို Client-side ဘက်မှာ အဓိကအလုပ်လုပ်တဲ့ App မျိုးမှာတော့ Controller မသုံးတော့ဘဲ Component ချင်း တိုက်ရိုက်ချိတ်ဆက် ရေးသားသွားလိုက်တာပဲ ဖြစ်ပါတယ်။
Well learned and thanks^^