How to use alpinejs along livewire with mini project

How to use alpinejs along livewire with mini project

First, we create a Laravel project called Alp-wire as follows:

composer create-project laravel/laravel Alp-wire

Then we install livewire with the following command in Laravel project:

composer require livewire/livewire

Then in the command line we use the following command to use livewire in Laravel project:

php artisan make:livewire welcome-page

Alp-wire / resources / views / welcome.blade.php

<!DOCTYPE html>
<html>

<head>
    <title>Alp-wire</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
    @livewireStyles
</head>

<body class="antialiased">
    @livewire('welcome-page')
    @livewireScripts
</body>

</html>

In the above code, we used Alpine cdn.

Alp-wire/app/Http/Livewire/WelcomePage.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class WelcomePage extends Component
{
    public function render()
    {
        return view('livewire.welcome-page');
    }
}

Alp-wire/resources/views/livewire/welcome-page.blade.php

            <div>
                <h1
                    class="text-3xl text-gray-200 hover:text-yellow-400 text-center mt-48 font-extrabold tracking-tight text-white sm:text-5xl">
                    Hello World!
                </h1>
            </div>

This way it is very easy to use livewire, of course you can also use tailwindcss along with livewire.

Then create a database and create a users table as follows:

Alp-wire/database/migrations/2014_10_12_000000_create_users_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->integer('phone');
            $table->integer('package');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
};

Alp-wire/app/Models/User.php

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'phone',
        'package',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Then we create another component as follows:

php artisan make:livewire Home-page

Alp-wire/app/Http/Livewire/WelcomePage.php

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Livewire\Component;

class WelcomePage extends Component
{
    public $name;
    public $email;
    public $phone;
    public $package;


    protected $rules = [
        "name" => "required|min:6",
        "email" => "required|email|unique:users",
        "phone" => "required|regex:/(0)[0-9]/|not_regex:/[a-z]/|min:9",
        "package" => "required",
    ];

    public function updated($propertyName)
    {
        $this->validateOnly($propertyName);
    }

    public function submit()
    {
        $data = [
            'name' => $this->name,
            'email' => $this->email,
            'phone' => $this->phone,
            'package' => $this->package
        ];
        $data = $this->validate();
        User::create($data);
    }

    public function render()
    {
        return view('livewire.Home-page');
    }
}

Alp-wire/app/Http/Livewire/HomePage.php

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Livewire\Component;

class HomeTable extends Component
{
    public function render()
    {
        return view('livewire.Home-table');
    }
}

Alp-wire/resources/views/livewire/welcome-page.blade.php

<div>
    @livewire('Home-page')
</div>

Alp-wire/resources/views/livewire/Home-page.blade.php

<div class="mt-8 ml-12">
    <h1 class="w-11/12 pb-4 text-4xl font-extrabold tracking-tight text-gray-900 border-b border-slate-300">
        SignUp</h1>

    <div class="flex">
        <form class="pt-4" wire:submit.prevent="submit">
            <div>
                <label for="name" class="block text-sm font-medium text-gray-700">Name</label>
                <input required type="text" name="name" wire:model="name" id="name"
                    class="block border rounded-md w-72">
                @error('name')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
                <input required type="text" name="email" wire:model="email" id="email"
                    class="block border rounded-md w-72">
                @error('email')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="phone" class="block text-sm font-medium text-gray-700">Phone</label>
                <input required type="text" name="phone" wire:model="phone" id="phone"
                    class="block border rounded-md w-72">
                @error('phone')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="package" class="block text-sm font-medium text-gray-700">Package</label>
                <select wire:model="package" name="package" class="block border rounded-md w-72">
                    <option>
                        choose one package
                    </option>
                    <option value="5">
                        5 days in week
                    </option>
                    <option value="4">
                        4 days in week
                    </option>
                    <option value="3">
                        3 days in week
                    </option>
                    <option value="2">
                        2 days in week
                    </option>
                </select>
            </div>
            <button type="submit"
                class="flex items-center justify-center px-8 py-3 mt-10 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md w-72 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Add</button>
        </form>
</div>

Now to use alpine, we do the following to add navigation:

Alp-wire/resources/views/livewire/Home-page.blade.php

<div class="mt-8 ml-12" x-data="{ open: false }">
    <h1 class="w-11/12 pb-4 text-4xl font-extrabold tracking-tight text-gray-900 border-b border-slate-300">
        SignUp</h1>

    <div x-show="open" class="px-4 py-3 text-teal-900 bg-teal-100 border-t-4 border-teal-500 rounded-b shadow-md"
        role="alert">
        <div class="flex">
            <div class="py-1"><svg class="w-6 h-6 mr-4 text-teal-500 fill-current"
                    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                    <path
                        d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM9 11V9h2v6H9v-4zm0-6h2v2H9V5z" />
                </svg></div>
            <div>
                <p class="font-bold">User Successfuly Saved!</p>
            </div>
        </div>
    </div>
    <div class="flex">
        <form class="pt-4" wire:submit.prevent="submit" @submit.prevent="open = true">
            <div>
                <label for="name" class="block text-sm font-medium text-gray-700">Name</label>
                <input required type="text" name="name" wire:model="name" id="name"
                    class="block border rounded-md w-72">
                @error('name')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
                <input required type="text" name="email" wire:model="email" id="email"
                    class="block border rounded-md w-72">
                @error('email')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="phone" class="block text-sm font-medium text-gray-700">Phone</label>
                <input required type="text" name="phone" wire:model="phone" id="phone"
                    class="block border rounded-md w-72">
                @error('phone')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="package" class="block text-sm font-medium text-gray-700">Package</label>
                <select wire:model="package" name="package" class="block border rounded-md w-72">
                    <option>
                        choose one package
                    </option>
                    <option value="5">
                        5 days in week
                    </option>
                    <option value="4">
                        4 days in week
                    </option>
                    <option value="3">
                        3 days in week
                    </option>
                    <option value="2">
                        2 days in week
                    </option>
                </select>
            </div>
            <button type="submit"
                class="flex items-center justify-center px-8 py-3 mt-10 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md w-72 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Add</button>
        </form>
</div>

Now to show the list of users using alpine, we do the following:

Alp-wire/app/Http/Livewire/WelcomePage.php

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Livewire\Component;

class WelcomePage extends Component
{
    public $name;
    public $email;
    public $phone;
    public $package;
    public $users;

    public function mount()
    {
        $this->users = User::all();
    }

    protected $rules = [
        "name" => "required|min:6",
        "email" => "required|email|unique:users",
        "phone" => "required|regex:/(0)[0-9]/|not_regex:/[a-z]/|min:9",
        "package" => "required",
    ];

    public function updated($propertyName)
    {
        $this->validateOnly($propertyName);
    }

    public function submit()
    {
        $data = [
            'name' => $this->name,
            'email' => $this->email,
            'phone' => $this->phone,
            'package' => $this->package
        ];
        $data = $this->validate();
        User::create($data);
    }

    public function render()
    {
        return view('livewire.Home-page');
    }
}

Alp-wire/app/Http/Livewire/HomePage.php

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Livewire\Component;

class BodyTable extends Component
{
    public $users;

    public function mount(User $users)
    {
        $this->users = $users;
    }

    public function render()
    {
        return view('livewire.body-table');
    }
}

Alp-wire/routes/web.php

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

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

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

Alp-wire/resources/views/livewire/Home-page.blade.php

<div class="mt-8 ml-12" x-data="{ open: false }">
    <h1 class="w-11/12 pb-4 text-4xl font-extrabold tracking-tight text-gray-900 border-b border-slate-300">
        SignUp</h1>
    <div x-show="open" class="px-4 py-3 text-teal-900 bg-teal-100 border-t-4 border-teal-500 rounded-b shadow-md"
        role="alert">
        <div class="flex">
            <div class="py-1"><svg class="w-6 h-6 mr-4 text-teal-500 fill-current"
                    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                    <path
                        d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM9 11V9h2v6H9v-4zm0-6h2v2H9V5z" />
                </svg></div>
            <div>
                <p class="font-bold">User Successfuly Saved!</p>
            </div>
        </div>
    </div>
    <div class="flex">
        <form class="pt-4" wire:submit.prevent="submit" @submit.prevent="open = true">
            <div>
                <label for="name" class="block text-sm font-medium text-gray-700">Name</label>
                <input required type="text" name="name" wire:model="name" id="name"
                    class="block border rounded-md w-72">
                @error('name')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
                <input required type="text" name="email" wire:model="email" id="email"
                    class="block border rounded-md w-72">
                @error('email')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="phone" class="block text-sm font-medium text-gray-700">Phone</label>
                <input required type="text" name="phone" wire:model="phone" id="phone"
                    class="block border rounded-md w-72">
                @error('phone')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="package" class="block text-sm font-medium text-gray-700">Package</label>
                <select wire:model="package" name="package" class="block border rounded-md w-72">
                    <option>
                        choose one package
                    </option>
                    <option value="5">
                        5 days in week
                    </option>
                    <option value="4">
                        4 days in week
                    </option>
                    <option value="3">
                        3 days in week
                    </option>
                    <option value="2">
                        2 days in week
                    </option>
                </select>
            </div>
            <button type="submit"
                class="flex items-center justify-center px-8 py-3 mt-10 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md w-72 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Add</button>
        </form>
        <div class="max-w-2xl mx-auto" x-show="open">
            <div class="relative overflow-x-auto shadow-md sm:rounded-lg">
                <div class="p-4">
                    <label for="table-search" class="sr-only">Search</label>
                    <div class="relative mt-1">
                        <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
                            <svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor"
                                viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
                                <path fill-rule="evenodd"
                                    d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
                                    clip-rule="evenodd"></path>
                            </svg>
                        </div>
                        <input type="text" id="table-search"
                            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-80 pl-10 p-2.5  dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
                            placeholder="Search for items">
                    </div>
                </div>
                <table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
                    <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
                        <tr>
                            <th scope="col" class="px-6 py-3">
                                name
                            </th>
                            <th scope="col" class="px-6 py-3">
                                email
                            </th>
                            <th scope="col" class="px-6 py-3">
                                phone
                            </th>
                            <th scope="col" class="px-6 py-3">
                                package
                            </th>
                            <th scope="col" class="px-6 py-3">
                                <span class="sr-only">Edit</span>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        //codes
                    </tbody>
                </table>
            </div>
            <script src="https://unpkg.com/flowbite@1.3.4/dist/flowbite.js"></script>
        </div>
    </div>
</div>

Alp-wire/resources/views/livewire/welcome-page.blade.php

<div>
    @livewire('Home-page', ['users' => $users])
</div>

To use alpine, we do the following:

Alp-wire/resources/views/livewire/Home-page.blade.php

<div class="mt-8 ml-12" x-data="{ open: false }">
    <h1 class="w-11/12 pb-4 text-4xl font-extrabold tracking-tight text-gray-900 border-b border-slate-300">
        SignUp</h1>
    <div x-show="open" class="px-4 py-3 text-teal-900 bg-teal-100 border-t-4 border-teal-500 rounded-b shadow-md"
        role="alert">
        <div class="flex">
            <div class="py-1"><svg class="w-6 h-6 mr-4 text-teal-500 fill-current"
                    xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                    <path
                        d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM9 11V9h2v6H9v-4zm0-6h2v2H9V5z" />
                </svg></div>
            <div>
                <p class="font-bold">User Successfuly Saved!</p>
            </div>
        </div>
    </div>
    <div class="flex">
        <form class="pt-4" wire:submit.prevent="submit" @submit.prevent="open = true">
            <div>
                <label for="name" class="block text-sm font-medium text-gray-700">Name</label>
                <input required type="text" name="name" wire:model="name" id="name"
                    class="block border rounded-md w-72">
                @error('name')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
                <input required type="text" name="email" wire:model="email" id="email"
                    class="block border rounded-md w-72">
                @error('email')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="phone" class="block text-sm font-medium text-gray-700">Phone</label>
                <input required type="text" name="phone" wire:model="phone" id="phone"
                    class="block border rounded-md w-72">
                @error('phone')
                    <span class="text-red-500">{{ $message }}</span>
                @enderror
            </div>

            <div class="mt-4">
                <label for="package" class="block text-sm font-medium text-gray-700">Package</label>
                <select wire:model="package" name="package" class="block border rounded-md w-72">
                    <option>
                        choose one package
                    </option>
                    <option value="5">
                        5 days in week
                    </option>
                    <option value="4">
                        4 days in week
                    </option>
                    <option value="3">
                        3 days in week
                    </option>
                    <option value="2">
                        2 days in week
                    </option>
                </select>
            </div>
            <button type="submit"
                class="flex items-center justify-center px-8 py-3 mt-10 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md w-72 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Add</button>
        </form>
        <div class="max-w-2xl mx-auto" x-show="open">
            <div class="relative overflow-x-auto shadow-md sm:rounded-lg" x-data="{
                search: '',
                @foreach ($users as $user) items: ['{{ $user->name }}'], @endforeach
                get filteredItems() {
                    return this.items.filter(
                        i => i.startsWith(this.search)
                    )
                }
            }">
                <div class="p-4">
                    <label for="table-search" class="sr-only">Search</label>
                    <div class="relative mt-1">
                        <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
                            <svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor"
                                viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
                                <path fill-rule="evenodd"
                                    d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
                                    clip-rule="evenodd"></path>
                            </svg>
                        </div>
                        <input type="text" id="table-search" x-model="search"
                            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-80 pl-10 p-2.5  dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
                            placeholder="Search for items">
                    </div>
                </div>
                <table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
                    <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
                        <tr>
                            <th scope="col" class="px-6 py-3">
                                name
                            </th>
                            <th scope="col" class="px-6 py-3">
                                email
                            </th>
                            <th scope="col" class="px-6 py-3">
                                phone
                            </th>
                            <th scope="col" class="px-6 py-3">
                                package
                            </th>
                            <th scope="col" class="px-6 py-3">
                                <span class="sr-only">Edit</span>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach ($users as $user)
                            <template x-for="item in filteredItems" :key="item">
                                <tr
                                    class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
                                    <td scope="row"
                                        class="px-6 py-4 font-medium text-gray-900 dark:text-white whitespace-nowrap">
                                        {{ $user->name }}
                                        <span class="invisible" x-text="item"></span>
                                    </td>
                                    <td class="px-6 py-4">
                                        {{ $user->email }}
                                    </td>
                                    <td class="px-6 py-4">
                                        {{ $user->phone }}
                                    </td>
                                    <td class="px-6 py-4">
                                        {{ $user->package }}
                                    </td>
                                    <td class="px-6 py-4 text-right">
                                        <a href="#"
                                            class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Edit</a>
                                    </td>
                                </tr>
                            </template>
                        @endforeach
                    </tbody>
                </table>
            </div>
            <script src="https://unpkg.com/flowbite@1.3.4/dist/flowbite.js"></script>
        </div>
    </div>
</div>

I hope you like this article. To see the source codes, you can refer to the following link.

Alp-wire