Skip to main content

blocs/admin: テーブルタイプの入力画面

blocs/admin: テーブルタイプの入力画面

複数のレコードを一括で入力できる画面の実装方法を説明します。

前提条件: blocs/admin がインストール済みであること

テンプレートの作成

data-loop 属性を使って、1件分の入力フォームを繰り返し表示します。

tbody data-loop=$books
  tr
    th 名前
    td 入力フィールド(name)

バリデーション条件の設定

ワイルドカード(*)を使って複数の入力項目を一括で指定します。エラーメッセージにはループのインデックスを使います。

!books.*.name = required_with:books.*.price
@error("books.".$loop->index.".name") エラーメッセージ表示 @enderror

コントローラーで初期データを作成

protected function prepareCreate()
{
    if (!old('books')) {
        $minRows = 5;
        $this->val['books'] = [];
        for ($rowNum = 0;  $rowNum < $minRows; $rowNum++) {
            $this->val['books'][] = [];
        }
    }
}

入力されていないデータを除外

protected function validateStore()
{
    $books = $this->request->input('books', []);

    if (is_array($books)) {
        $books = array_values(array_filter($books, function ($book) {
            if (! is_array($book)) {
                return true;
            }

            $filled = array_filter($book, function ($value) {
                if (is_string($value)) {
                    $value = trim($value);
                }

                return $value !== null && $value !== '';
            });

            return ! empty($filled);
        }));

        $this->request->merge(['books' => $books]);
    }

    parent::validateStore();
}

入力データの一括登録

protected function executeStore($requestData = [])
{
    $books = $requestData['books'] ?? [];

    if (! is_array($books) || empty($books)) {
        return;
    }

    DB::transaction(function () use ($books) {
        foreach ($books as $book) {
            if (! is_array($book)) {
                continue;
            }

            $model = Book::create($book);
        }
    });
}