Livewire emitUpで親コンポーネントにイベントを送るには?emitUp
「$this->emit($eventName, …$params)->up()」の説明は「ページの親コンポーネントにイベントを発行する」と記載されています。「もしかしたら、先祖まではイベントは届かないのかな?」と疑問を持ちましたので調査してみます。
先に結論になりますが、emitUp で先祖までイベントは届いてしまいます。
現状、親のみにイベントを送るには、emitUp でコンポーネントIDも送信して、previouslyRenderedChildrenプロパティ で確認する方法かなぁ。今のところ。
↓↓↓
public function isChild( $childId ) {
return collect($this->previouslyRenderedChildren)->pluck(‘id’)->search($childId);
}
↓
2022年12月4日現在、 $this->emitParentメソッド で親コンポーネントのみにイベントを送れるようになりました。
完成系は↓こちらです。
public function isChild($childId) {
return collect($this->previouslyRenderedChildren)->pluck('id')->search($childId);
}
手順
Laravel と Livewire をインストールして、emitUp のサンプルプログラムを作成してみます。
- プロジェクト名(emitUp)を決めて以下のコマンドを実行します。
curl -s https://laravel.build/emitUp | bash
インストール時にプロジェクト名のディレクトリが作成されます。
- インストールの最後に sudo でパスワードの入力を求められます。
↓下のメッセージが表示されてインストールは終わります。
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Get started with: cd emitUp && ./vendor/bin/sail up
- sail のエイリアスを定義します。
echo "alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'" >> ~/.bashrc
source ~/.bashrc
Laravel のインストールはここまで。
- 「sail up」でコンテナを起動します。
cd emitUp && sail up -d
- ララベルのトップディレクトリで、Livewireパッケージ をインストールします。
sail composer require livewire/livewire
- 次のコマンドを実行して、parent-formコンポーネント を生成します。
sail artisan make:livewire parent-form
$ sail artisan make:livewire parent-form
COMPONENT CREATED ?
CLASS: app/Http/Livewire/ParentForm.php
VIEW: resources/views/livewire/parent-form.blade.php
次の 2つ のファイルが生成されます。
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class ParentForm extends Component
{
public function render()
{
return view('livewire.parent-form');
}
}
<div>
{{-- Care about people's approval and you will be their prisoner. --}}
</div>
※因みに、render メソッド を定義しなくても livewire.parent-form は呼び出されます。
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class ParentForm extends Component
{
}
- 生成された parent-formコンポーネント のクラスとビューを次のように置き換えます。
app/Http/Livewire/ParentForm.php
<?php
namespace App\Http\Livewire;
class ParentForm extends \Livewire\Component {
public $bgcolor = "#FFF";
protected $listeners = ['emitup_test'];
public function emitup_test( $childId = '' ) {
\Log::debug(__CLASS__);
if ('' != $childId)
if (false === collect($this->previouslyRenderedChildren)->pluck('id')->search($childId))
return;
$this->bgcolor = "#00F";
}
}
resources/views/livewire/parent-form.blade.php
<div style="text-align:center;background-color:{{ $bgcolor }};padding:1em;">
<h1>Parent</h1>
<button type="button" wire:click="emitup_test">emitUp</button>
<livewire:child-form>
</div>
- child-formコンポーネント のクラスとビューを作成します。
app/Http/Livewire/ChildForm.php
<?php
namespace App\Http\Livewire;
class ChildForm extends \Livewire\Component {
public $bgcolor = "#FFF";
protected $listeners = ['emitup_test'];
public function emitup_test( $childId = '' ) {
\Log::debug(__CLASS__);
if ('' != $childId)
if (false === collect($this->previouslyRenderedChildren)->pluck('id')->search($childId))
return;
$this->bgcolor = "#0F0";
}
}
resources/views/livewire/child-form.blade.php
<div style="text-align:center;background-color:{{ $bgcolor }};padding:1em;">
<h1>Child</h1>
<button type="button" wire:click="emitup_test">emitUp</button>
<livewire:grandchild-form>
</div>
- grandchild-formコンポーネント のクラスとビューを作成します。
app/Http/Livewire/GrandchildForm.php
<?php
namespace App\Http\Livewire;
class GrandchildForm extends \Livewire\Component {
public $bgcolor = "#FFF";
protected $listeners = ['emitup_test'];
public function emitup_test( $childId = '' ) {
\Log::debug(__CLASS__);
if ('' != $childId)
if (false === collect($this->previouslyRenderedChildren)->pluck('id')->search($childId))
return;
$this->bgcolor = "#F00";
$this->emit('emitup_test')->up();
}
public function emitup_only_parent() {
\Log::debug(__CLASS__);
$this->emit('emitup_test',$this->id)->up();
}
}
resources/views/livewire/grandchild-form.blade.php
<div style="text-align:center;background-color:{{ $bgcolor }};padding:1em;">
<h1>Grandchild</h1>
<button type="button" wire:click="emitup_test">emitUp message</button>
<button type="button" wire:click="emitup_only_parent">emitUp only-parent</button>
</div>
- resources/views/index.blade.php ファイル を作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<livewire:styles />
</head>
<body>
<livewire:parent-form />
<livewire:scripts />
</body>
</html>
- routes/web.php にルートを追加します。
Route::get('/', fn() => view('index'));
- ブラウザで確認します。
[2022-11-15 01:01:44] local.DEBUG: App\Http\Livewire\GrandchildForm
[2022-11-15 01:01:44] local.DEBUG: App\Http\Livewire\ChildForm
[2022-11-15 01:01:44] local.DEBUG: App\Http\Livewire\ParentForm
↑上が Grandchild の「emitUp message」ボタン を押した実行結果です。「$this->emit()->up()」で、Child と Parent にメッセージが送信されています。
↑上が Grandchild の「emitUp only-parent」ボタン を押した実行結果です。emitup_testメソッドで子供の componentId なら処理するようにしています。
以上