Livewire 親子のコンポーネントについて、親のプロパティを更新するには?oyako2
子コンポーネントを更新した時に、子コンポーネントからイベントを発行して(emitUp)、親コンポーネントのプロパティを更新しようと思います。
親子コンポーネントについてイベントを発行して値の受け渡しはできますが、なんか面倒なんですよね。
もっと良いやり方があるんはずと思い調査をしました。
そして見つけたのが「Livewire v3 」。
きっと私が考えていることができそう。$parent とか @prop です。
https://www.makeuseof.com/whats-new-in-livewire-v3-laravel-framework/
完成は↓こちらです。
手順
Laravel と Livewire をインストールして、ライブワイヤーの親子のコンポーネントを作成してみます。
- プロジェクト名(oyako2)を決めて以下のコマンドを実行します。
curl -s https://laravel.build/oyako2 | bash
インストール時にプロジェクト名のディレクトリが作成されます。
- インストールの最後に sudo でパスワードの入力を求められます。
↓下のメッセージが表示されてインストールは終わります。
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Get started with: cd oyako2 && ./vendor/bin/sail up
- sail のエイリアスを定義します。
echo "alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'" >> ~/.bashrc
source ~/.bashrc
Laravel のインストールはここまで。
- 「sail up」でコンテナを起動します。
cd oyako2 && sail up -d
- ララベルのトップディレクトリで、Livewireパッケージをインストールします。
sail composer require livewire/livewire
- Livewire のクラスとビューを作成するため、ディレクトリを作成します。
mkdir app/Http/Livewire/
mkdir resources/views/livewire
- ライブワイヤーの親コンポーネントを作成します。app/Http/Livewire/ParentComponent.php
<?php
namespace App\Http\Livewire;
class ParentComponent extends \Livewire\Component
{
public $name1 = '親から初期値を設定1';
public $name2 = '親から初期値を設定2';
public $foo; // 意味無し
protected $listeners = ['update'=>'onUpdateEvent'];
public function onUpdateEvent($name,$value)
{
\Log::debug(__METHOD__);
\Log::debug([$name,$value]);
$this->$name = $value;
}
public function boot() { \Log::debug(__METHOD__); }
public function booted() { \Log::debug(__METHOD__); }
public function mount() { \Log::debug(__METHOD__); }
public function dehydrate() { \Log::debug(__METHOD__); }
public function dehydrateFoo($value) { \Log::debug(__METHOD__); }
public function hydrateFoo($value) { \Log::debug(__METHOD__); }
public function hydrate() { \Log::debug(__METHOD__); }
public function updating($name,$value) { \Log::debug(__METHOD__); }
public function updated($name,$value) { \Log::debug(__METHOD__); }
public function updatingFoo($value) { \Log::debug(__METHOD__); }
public function updatedFoo($value) { \Log::debug(__METHOD__); }
public function updatingFooBar($value) { \Log::debug(__METHOD__); }
public function updatedFooBar($value) { \Log::debug(__METHOD__); }
public function render()
{
\Log::debug(__METHOD__);
return <<<'EOS'
<div style="padding:1em;background-color:#AFA;">
親コンポーネント<br>
<livewire:child-component name="name1" :value="$name1" />
{{ $name1 }}
<livewire:child-component name="name2" :value="$name2" />
{{ $name2 }}
</div>
EOS;
}
}
イベントをキャッチするには「protected $listeners」に定義します。
- ライブワイヤーの子コンポーネントを作成します。app/Http/Livewire/ChildComponent.php
<?php
namespace App\Http\Livewire;
class ChildComponent extends \Livewire\Component
{
public $name;
public $value;
public $foo; // 意味無し
public function boot() { \Log::debug(__METHOD__); }
public function booted() { \Log::debug(__METHOD__); }
public function mount() { \Log::debug(__METHOD__); }
public function dehydrate() {
\Log::debug(__METHOD__);
\Log::debug('* emitUp *');
$this->emit('update',$this->name,$this->value)->up();
}
public function dehydrateFoo($value) { \Log::debug(__METHOD__); }
public function dehydrateBoo($value) { \Log::debug(__METHOD__); }
public function hydrate() { \Log::debug(__METHOD__); }
public function hydrateFoo($value) { \Log::debug(__METHOD__); }
public function updating($name,$value) { \Log::debug(__METHOD__); }
public function updated($name,$value) { \Log::debug(__METHOD__); }
public function updatingFoo($value) { \Log::debug(__METHOD__); }
public function updatedFoo($value) { \Log::debug(__METHOD__); }
public function updatingFooBar($value) { \Log::debug(__METHOD__); }
public function updatedFooBar($value) { \Log::debug(__METHOD__); }
public function render()
{
\Log::debug(__METHOD__);
return <<<'EOS'
<div style="padding:1em;background-color:#EFE;">
子コンポーネント<br>
<input type="text" wire:model="value">
Hello {{ $value }}
<br>
<button wire:click="click">クリア</button><br>
</div>
EOS;
}
public function click() {
\Log::debug(__METHOD__);
$this->value = 'クリア';
}
}
親にイベントを送るには「emit()->up()」を使います。
- ライブワイヤーをテストするビューを作成します。resources/views/livewire.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<livewire:styles />
</head>
<body>
<livewire:parent-component />
<livewire:scripts />
</body>
</html>
- routes/web.php にルートを定義します。
Route::get('/',fn() => view('livewire'));
これでブラウザでアクセスできるようになりました。
- ブラウザでアクセスしてみましょう。
キーボードから子コンポーネントのテキストボックスに何か入力すると、隣と下の文字(「親から値を設定1」)が変わります。子コンポーネントからイベントを発行して、親コンポーネントのプロパティを変更することができました。
今回、子コンポーネントの dehydrateフック でイベントを発行しました。
当初は updatedフック でイベントを発行していました。テキストボックスに入力した場合には、updatedフック が呼び出されますが、クリアボタンを押してプロパティを書き換えた場合には、updatedフック は呼び出されません。dehydrateフック でイベントを発行しない場合は、updateフック と clickメソッド でイベント発行しなくてはなりません。
以上