はじめに
LaravelとAlpine.jsを組み合わせて使用する際、フロントの操作が楽になります。
しかしながらデータ処理をフロントで使用する場合、バックエンドからのデータをx-dataにセットする際、少し手間取ったのでメモります。
データのセット
Alpine.jsで使用するデータをセットする際、のコンポーネントが初期化される前にセットする必要があります。
以下は、Alpine.jsの初期化前にデータを設定する方法を示した例です。
バックエンドからのデータをフロントで使えるようにセットします。
Bladeテンプレート
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Form</title>
<script>
// PHPでJavaScript変数を設定
window.defaultRows = @json($defaultRows);
</script>
<script src="{{ asset('js/cdn.min.js') }}" defer></script>
</head>
<body>
<h1>Dynamic Form</h1>
@if (session('success'))
<div style="color: green;">
{{ session('success') }}
</div>
@endif
{{-- デバッグ情報を表示 --}}
<pre>{{ var_export($defaultRows, true) }}</pre>
<pre id="debug"></pre>
{{-- Alpine.jsのx-dataでJavaScript変数を使用 --}}
<form x-data="{ rows: window.defaultRows }" x-init="console.log(rows)" method="POST" action="{{ route('form.submit') }}">
@csrf
<template x-for="(row, index) in rows" :key="index">
<div>
<label>
<span x-text="index + 1"></span> 番目のフィールド:
<input type="text" x-model="row.field" name="rows[][field]" />
</label>
</div>
</template>
<button type="button" @click.prevent="rows.push({ field: '' });">行の追加</button>
<input type="submit" value="送信">
</form>
<script>
document.addEventListener('DOMContentLoaded', () => {
// デバッグ情報を表示
document.getElementById('debug').textContent = JSON.stringify(window.defaultRows, null, 2);
});
</script>
</body>
</html>
説明
ポイントは以下になります。
-
<head>
内でJavaScript変数を設定:-
Alpine.jsのスクリプトを読み込む前に、バックエンドからのデータを
window.defaultRows
にセットします。
window.defaultRows = @json($defaultRows);
その際使用する@jsonディレクティブは、LaravelのBladeテンプレートエンジンの機能です。
このディレクティブは、PHPの配列やオブジェクトをJSON形式の文字列に変換し、そのままHTMLに出力するために使用されます。
例: @json($array)は、$arrayをJSONエンコードし、その結果をHTMLに出力します。 -
これにより、Alpine.jsのコンポーネントが初期化される前にデータが設定されます。
-
-
<script defer>
でAlpine.jsを読み込み:-
defer
属性を使用して、HTMLの解析が完了するまでスクリプトの実行を遅らせます。ただし、先に設定したwindow.defaultRows
はすでに利用可能です。
-
-
x-data
でwindow.defaultRows
を使用:-
x-data
ディレクティブ内で、rows
にwindow.defaultRows
を設定します。これにより、Alpine.jsが初期化されると同時にデータが設定されます。
-
終わりに
x-dataに@json($変数)をセットできないのが少々面倒でした。
bladeで正しくエスケープ処理がされず、処理するには現状工夫が必要そうです。
その他
以下今回使用したソースを記載します
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use App\Http\Controllers\FormController;
Route::get('/form', [FormController::class, 'showForm'])->name('form.show');
Route::post('/form', [FormController::class, 'submitForm'])->name('form.submit');
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FormController extends Controller
{
public function showForm()
{
// デフォルトの行データを設定
$defaultRows = [
['field' => 'default value 1'],
['field' => 'default value 2'],
];
return view('form', compact('defaultRows'));
}
public function submitForm(Request $request)
{
// フォームのデータを処理します。ここではデータのバリデーションと保存などを行います。
$validatedData = $request->validate([
'rows' => 'required|array',
'rows.*.field' => 'required|string|max:255',
]);
// データの処理例
foreach ($validatedData['rows'] as $row) {
// 各行のデータを処理します。
// 例: DBに保存するなど
}
return redirect()->route('form.show')->with('success', 'データが送信されました。');
}
}
参考