Livewire 親子のコンポーネントについて、親のプロパティを更新するには?oyako2

ショコラ
ショコラ

Livewire 親子のコンポーネントについて、親のプロパティを更新するには?oyako2

子コンポーネントを更新した時に、子コンポーネントからイベントを発行して(emitUp)、親コンポーネントのプロパティを更新しようと思います。

親子コンポーネントについてイベントを発行して値の受け渡しはできますが、なんか面倒なんですよね。
もっと良いやり方があるんはずと思い調査をしました。
そして見つけたのが「Livewire v3 」
きっと私が考えていることができそう。$parent とか @prop です。
https://www.makeuseof.com/whats-new-in-livewire-v3-laravel-framework/

もっさん先輩
もっさん先輩

完成は↓こちらです。

手順

Laravel と Livewire をインストールして、ライブワイヤーの親子のコンポーネントを作成してみます。

  1. プロジェクト名(oyako2)を決めて以下のコマンドを実行します。
curl -s https://laravel.build/oyako2 | 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 oyako2 && ./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 oyako2 && sail up -d
  1. ララベルのトップディレクトリで、Livewireパッケージをインストールします。
sail composer require livewire/livewire
  1. Livewire のクラスとビューを作成するため、ディレクトリを作成します。
mkdir app/Http/Livewire/
mkdir resources/views/livewire
  1. ライブワイヤーの親コンポーネントを作成します。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」に定義します。

  1. ライブワイヤーの子コンポーネントを作成します。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()」を使います。

  1. ライブワイヤーをテストするビューを作成します。resources/views/livewire.blade.php
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <livewire:styles />
  </head>
  <body>
    <livewire:parent-component />
    <livewire:scripts />
  </body>
</html>
  1. routes/web.php にルートを定義します。
Route::get('/',fn() => view('livewire'));

これでブラウザでアクセスできるようになりました。

  1. ブラウザでアクセスしてみましょう。

キーボードから子コンポーネントのテキストボックスに何か入力すると、隣と下の文字(「親から値を設定1」)が変わります。子コンポーネントからイベントを発行して、親コンポーネントのプロパティを変更することができました。

今回、子コンポーネントの dehydrateフック でイベントを発行しました。
当初は updatedフック でイベントを発行していました。テキストボックスに入力した場合には、updatedフック が呼び出されますが、クリアボタンを押してプロパティを書き換えた場合には、updatedフック は呼び出されません。dehydrateフック でイベントを発行しない場合は、updateフック と clickメソッド でイベント発行しなくてはなりません。

以上

Scroll to Top