0
Help us understand the problem. What are the problem?

posted at

updated at

Symfony版Livewireこと、Live Componentさん

Symfony Advent Calendar 2021の記事です。
今回はSymfony UXの新機能、Live Componentについて書きます。

Symfony UXとは

なるべくサーバサイドのことに注力できるように、フロントエンドのUXに関するJavaScriptとサーバサイドをうまいこと繋ぎ込んでくれるライブラリ群です。
composerでサーバサイド側のプログラムとnpmパッケージをダウンロードして利用します。
2021年12月現在、以下が用意されています。

name 内容
UX Chart.js Chart.jsがいい感じにつかえるやつ
UX Cropper.js Cropper.jsがいい感じにつかえるやつ
UX Dropzone ドラッグ&ドロップでファイルアップロードできるようにしてくれるやつ
UX LazyImage 画像遅延読み込みをいい感じにしてくれるやつ
UX Swup Swupがいい感じにつかえるやつ
UX Turbo Hotwire Turboがいい感じにつかえるやつ
Twig Component 【実験段階】 再利用可能なTwigコンポーネントがつくれるやつ
Live Component 【実験段階】 Ajaxで再描画できるTwigコンポーネントがつくれるやつ

Live Componentを使ってみる。。前に

Live Componentは、Livewire、Phoenix LiveViewにインスパイアされて作成されたようです。上記で書いた通り、Twig Componentの一種です。まずはTwig Componentについて知る必要があります。

Twig Componentについて

Twig Componentは、コンポーネントクラスとTwigテンプレートのセットで、他のテンプレート上から呼び出すことができます。イメージ的にはEmbed Controllerに似ています。Live Componentもですが、実験段階なライブラリになります。

Twig Componentはいたってシンプルに作ることができます。まずはコンポーネントクラス。

src/Compoenents/HelloComponent.php
namespace App\Components;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('hello')]
class HelloComponent
{
    public string $name = '';

    public function getGreet(): string
    {
        return sprintf('こんにちは、%sさん', $this->name);
    }
}

アトリビュートで、#[AsTwigComponent('hello')]をつけることで、helloという名前のコンポーネントとして利用することができます。
nameを使ってgetGreet()で挨拶を返します。今回は使っていませんが、当然オートワイヤリング可能です。続いてコンポーネントで使うテンプレート。

templates/components/hello.html.twig
<div class="greet">
{{ this.greet }}
</div>

コンポーネントクラスのGetterメソッドにはthis.***という形でアクセスできます。ここではthis.greetgetGreet()にアクセスしています。
最後に、コンポーネントを使う側のテンプレートです。

templates/index.html.twig
<div>
<h3>あいさつ</h3>
{{ component('hello', {name: 'ほげほげ'}) }}
</div>

{{ component('コンポーネント名, 引数) }}`でコンポーネントを呼び出すことができます。引数を設定するとパブリックなプロパティに値を代入してくれます。

上記の結果は、

<div>
<h3>あいさつ</h3>
<div class="greet">
こんにちは。ほげほげさん
</div>
</div>

となります。べんりー。

Live Componentを使ってみる。

さて、本題のLive Componentです。Live Componentでは、すこし記述がかわります。まずはクラス。

src/Compoenents/HelloComponent.php
namespace App\Components;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+ use Symfony\UX\LiveComponent\DefaultActionTrait;

- #[AsTwigComponent('hello')]
+ #[AsLiveComponent('hello')]
class HelloComponent
{
+    use DefaultActionTrait;
+
+   #[LiveProp(writable: true)]
    public string $name = '';

    public function getGreet(): string
    {
        return sprintf('こんにちは、%sさん', $this->name);
    }
}

アトリビュートが#[AsTwigComponent('hello')]から#[AsLiveComponent('hello')]に変更しました。Live Componentへはこれだけで変更されます。
続いてuse DefaultActionTrait;の追加ですが、再描画行う際にクラス内の__invoke()を実行するようになっているので、何もしない__invoke()メソッドを追加します。なお、Live Componentは実質Controllerとのこと。
最後にプロパティの$nameに#[LiveProp(writable: true)]を追加します。LivePropは該当のプロパティをステートフルプロパティに変更します。オプションのwritable: trueをつけることで、上書き可能なプロパティになります。

続いてテンプレート。

templates/components/hello.html.twig
- <div class="greet">
+ <div class="greet" {{ init_live_component(this) }}>
+     <input type="text" name="name" value="{{ this.name }}" data-action="live#update">
{{ this.greet }}
</div>

divタグに{{ init_live_component(this) }}が追加されました。これはライブコンポーネントの初期化が行われます。Symfony UXはStimulusを使用しており、Stimulusの初期化の記述をこれで追加します。

また、名前が変えれるように入力フォームを用意し、data-action="live#update"を追加しています。テキストボックスにdata-actionを追加すると、入力内容が変わるごとにlive#updateが実行され、Ajax経由でHelloComponent::__invoke()の実行結果を取得して、再描画を行います。

呼び出す側は修正の必要がありません。

では実行してみましょう。

このような感じで、入力したテキストがすぐに反映されています。
今回のサンプルは単純なものでしたが、DBのデータを扱ったり認可・認証をからめたコンポーネントも作れるようです。
例えば、

こんなのとか。
実験段階なので、まだまだ改修が入りそうですが、ページ再読み込みストレスをかなり軽減してくれる機能となっていて、Symfony UXの中でも今後がとても楽しみな機能です。ぜひ一度お試しください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?