Livewire emitUpで親コンポーネントにイベントを送るには?emitUp

ショコラ
ショコラ

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 のサンプルプログラムを作成してみます。

  1. プロジェクト名(emitUp)を決めて以下のコマンドを実行します。
curl -s https://laravel.build/emitUp | bash

インストール時にプロジェクト名のディレクトリが作成されます。

  1. インストールの最後に 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
  1. sail のエイリアスを定義します。
echo "alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'" >> ~/.bashrc
source ~/.bashrc

Laravel のインストールはここまで。

  1. 「sail up」でコンテナを起動します。
cd emitUp && sail up -d
  1. ララベルのトップディレクトリで、Livewireパッケージ をインストールします。
sail composer require livewire/livewire
  1. 次のコマンドを実行して、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
{
}
  1. 生成された 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>
  1. 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>
  1. 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>
  1. resources/views/index.blade.php ファイル を作成します。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <livewire:styles />
  </head>
  <body>
    <livewire:parent-form />
    <livewire:scripts />
  </body>
</html>
  1. routes/web.php にルートを追加します。
Route::get('/', fn() => view('index'));
  1. ブラウザで確認します。
[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 なら処理するようにしています。

以上

Scroll to Top