Laravel JetStream Livewire CRUD /Modal

Laravel

「composer create-project」でLaravelプロジェクトを作成

composer create-project laravel/laravel laravel_modal

JetStreamのインストール手順

composer require laravel/jetstream
php artisan jetstream:install livewire --teams

npm install と npm run dev を実行します。

npm install
npm run dev

データベースをマイグレーションを実行

php artisan migrate

マイグレーションの作成

php artisan make:migration create_create_target_users_table --table=target_users
    public function up()
    {
        Schema::create('target_users', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable()->comment('氏名');
            $table->string('email')->uniqe()->comment('メールアドレス');
            $table->timestamps();
        });
    }

マイグレーションを実行

php artisan migrate

Livewireコンポーネントの作成

php artisan make:livewire targetusers/targetusers

以下のように作成されます。

app/Http/Livewire//Targetusers/Targetusers.php
resources\views/livewire/targetusers\targetusers.blade.php

モデル作成

php artisan make:model TargetUser

追加します。

    // 変更可能なカラム
    protected $fillable = [
        'name',
        'email',
    ];

ルーティング作成

use App\Http\Livewire\Targetuser\Targetuser;
Route::get('/target', Targetuser::class)->name('targetuser');

コンポーネントの更新

app/Http/Livewire/Targetusers/.php

<?php

namespace App\Http\Livewire\Targetusers;
use App\Models\TargetUser;

use Livewire\Component;

class Targetusers extends Component
{
    public $Targetusers, $name, $email,$targetusers_id;
    public $isOpen = 0;

    public function render()
    {
        $TargetUsers = TargetUser::all();
        return view('livewire.targetusers.targetusers', compact('TargetUsers'));
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function create()
    {
        $this->resetInputFields();
        $this->openModal();
    }
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function openModal()
    {
        $this->isOpen = true;
    }
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function closeModal()
    {
        $this->isOpen = false;
    }    

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    private function resetInputFields(){
        $this->name = '';
        $this->email = '';
       
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function store()
    {
        $this->validate([
            'name' => 'required',
            'email' => 'required',
        ]);
   
        TargetUser::updateOrCreate(['id' => $this->targetusers_id], [
            'name' => $this->name,
            'email' => $this->email
        ]);
  
        session()->flash('message', 
            $this->targetusers_id ? '正常に登録されました。' : '正常に作成されました。');
  
        $this->closeModal();
        $this->resetInputFields();
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function edit($id)
    {

        $TargetUser = TargetUser::findOrFail($id);
        $this->targetusers_id = $TargetUser->id;
        $this->name = $TargetUser->name;
        $this->email = $TargetUser->email;
    
        $this->openModal();
    }

     /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function delete($id)
    {
        TargetUser::find($id)->delete();
        session()->flash('message', '正常に削除されました。');
    }
}

追加・更新するbladeファイル作成/ 以下追記します。

resources/livewire/Targetusers/Targetusers.blade.php

            <button wire:click="create()" class="bg-blue-500 hover:bg-blue-700 text-white py-1 mb-6 px-3 rounded my-3 mt-1">登録</button>
            @if($isOpen)
                @include('livewire.targetusers.create')
            @endif

ダイアログ「resources/views/Targetusers/create.blade.php」を次のように作成します。

<div class="fixed z-10 inset-0 overflow-y-auto ease-out duration-400">
    <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
        <div class="fixed inset-0 tansition-opacity">
            <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
        </div>
        <span class="hidden sm:inline-block sm:aligh-middle sm:h-screen"></span>
        <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
            <form>
                <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
                    <div class="">
                        <div class="mb-4">
                            <label for="title" class="block text-gray-700 text-sm font-bold mb-2">Title</label>
                            <input type="text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="title" placeholder="Enter Title" wire:model="title">
                            @error('title') <span class="text-red-500">{{ $message }}</span>@enderror       
                        </div>
                        <div class="mb-4">
                            <label for="description" class="block text-gray-700 text-sm font-bold mb-2">Description</label>
                            <textarea  id="description" cols="30" rows="10" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="Enter Discription" wire:model="description"></textarea>
                            @error('description') <span class="text-red-500">{{ $message }}</span>@enderror       
                        </div>
                    </div>
                </div>
                <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                    <span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
                        <button wire:click.prevent="store()" type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-green-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">
                            Save
                        </button>
                    </span>
                    <span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
                        <button wire:click="closeModal()" type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-green-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">
                            Cancel
                        </button>
                    </span>
                </div>
            </form>
        </div>
    </div>
</div>
image.png

以下の参照を追加する必要があります。追加しないと、最初表示する際、一瞬開いて閉じられます。

<script src="https://cdn.tailwindcss.com/?plugins=forms"></script>

コメント