3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

livewireで入力フォームの数を動的に制御

Posted at

はじめに

livewireで入力フォームの数を動的に増やしたり消したりする機能を実装する機会があったので、メモがてら。

環境

Laravel8.x, livewire, bootstrap4
参照:【Laravel】Laravel-AdminLTEとlivewireを布教したい
laravel8系とbootstrap4があれば何でも良いです。

完成品

image.png
追加ボタンクリックで「商品名、価格、削除ボタン」がセットのフォームを追加
削除ボタンクリックで指定のフォームの削除
登録ボタンで何かしらの処理実行

コード

コマンドでlivewireファイルを作成

php artisan make:livewire Sample0404
app/Http/Livewire/Sample0404.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Sample0404 extends Component
{
    public $products = [];

    protected $rules = [
        'products.*.name' => 'required',
        'products.*.price' => 'required',
    ];

    protected $validationAttributes = [
        'products.*.name' => '商品名',
        'products.*.price' => '価格',
    ];

    public function mount()
    {
        $this->products = [
            ['name' => 'みかん','price'=>2000],
            ['name' => 'りんご','price'=>1000]
        ];
    }

    public function render()
    {
        return view('livewire.sample0404')
            ->extends('adminlte::page')
            ->section('content');
    }

    public function add()
    {
        $this->products[] = ['name' => null,'price' =>null];
    }

    public function delete($key)
    {
        unset($this->products[$key]);
    }

    public function create()
    {
        $this->validate();
        dd('ok');
    }
}
resources/views/livewire/sample0404.blade.php
<div class="pt-2">
    <div class="col-5">
        <button type="button" class="btn btn-info col-2 mb-3" wire:click.prevent="add()">追加</button>
        @foreach($products as $key => $product)
            <div class="card card-body">
                <div class="text-right">
                    <button type="button" class="btn btn-danger col-2" wire:click.prevent="delete({{$key}})">削除</button>
                </div>
                <div class="row">
                    <div class="form-group col-md-6">
                        <label for="products.{{ $key }}.name">商品名</label>
                        <input type="text" name="products.{{ $key }}.name" class="form-control"
                               id="products.{{ $key }}.name" wire:model.defer="products.{{ $key }}.name">

                        @error("products.$key.name")
                        <span class="invalid-feedback d-block" role="alert">
                                    <strong>{{ $errors->first("products.$key.name") }}</strong>
                                </span>
                        @enderror
                    </div>

                    <div class="form-group col-md-6">
                        <label for="products.{{ $key }}.price">価格</label>
                        <input type="text" name="products.{{ $key }}.price" class="form-control"
                               id="products.{{ $key }}.price" wire:model.defer="products.{{ $key }}.price">

                        @error("products.$key.price")
                        <span class="invalid-feedback d-block" role="alert">
                                    <strong>{{ $errors->first("products.$key.price") }}</strong>
                                </span>
                        @enderror
                    </div>
                </div>
            </div>
        @endforeach
        <button type="button" class="btn btn-success col-2" wire:click.prevent="create">登録</button>
    </div>
</div>

ざっくり説明

1.mountメソッドに既存データを入れる

    public function mount()
    {
        $this->products = [
            ['name' => 'みかん','price'=>2000],
            ['name' => 'りんご','price'=>1000]
        ];
    }

mountメソッドはページアクセス時のみに一度だけ動く処理
DB連携する場合は既に登録されているデータを配列化して入れましょう。あくまで一例です。

    public function mount()
    {
        $this->products = Hoge::select(['name','price'])->get(['name','price'])->toArray();
    }

2.addメソッドでproduts配列に連想配列を追加

<button type="button" class="btn btn-info col-2 mb-3" wire:click.prevent="add()">追加</button>
    public function add()
    {
        $this->products[] = ['name' => null,'price' =>null];
    }

配列を追加することでblade側のforeachで回される要素が増えるので画面に1つフォームが追加されます。

3.deleteメソッドでフォームを削除

<button type="button" class="btn btn-danger col-2" wire:click.prevent="delete({{$key}})">削除</button>
    public function delete($key)
    {
        unset($this->products[$key]);
    }

deleteメソッドに配列のキーを渡して配列から削除します。画面上に反映されるとフォームが消えます

まとめ

こんな感じにphpの記述だけで動的にフォームを追加したり削除したりできます。
あくまで簡易的な一例なので、ちゃんとDBと連携する場合には要件に合わせてロジックを考えましょう。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?