🎻

[Symfony] EasyAdminのフォームフィールドにStimulusの処理を当てる

2022/01/27に公開

やりたかったこと

やり方

0. Stimulusについておさらい

symfony/webpack-encore-bundleレシピ を実行すると、@hotwired/stimulus@symfony/stimulus-bridge を依存に含む package.json が展開され、Stimulusを使って書いたJSの処理をSymfonyアプリに簡単に統合できるようになっています。

Stimulus自体についての細かい説明はこの記事では割愛しますが、ググれば丁寧な解説が色々見つかると思います!🙏

symfony/webpack-encore-bundle のレシピを実行した時点で、

  • assets/app.js
  • assets/bootstrap.js
  • assets/controllers.json
  • assets/contollers/hello_controller.js

などのStimulus関係のファイルが一式作成されており、webpack.config.js

.addEntry('app', './assets/app.js')
.enableStimulusBridge('./assets/controllers.json')

この2行が記載済みになっているため、HTML(Twig)側で

  • app エントリーのアセットを読み込んで
  • 適当なHTML要素に data-controller="hello" を付加する

だけで、その要素に assets/controllers/hello_controller.js の処理 が適用されて、

Hello Stimulus! Edit me in assets/controllers/hello_controller.js

というインナーテキストが表示されます👌

1. Stimulusのコントローラを実装

というわけで、実際にEasyAdminのフォームフィールドに適用したい処理を書いたStimulusのコントローラを実装すれば、あとは data-controller="コントローラ名" を付与するだけでよいと分かりました。

今回は具体例として、郵便番号が入力されたらAPIから住所を取得して住所入力欄を補完する という処理を書いてみましょう。

// assets/controllers/zipCode_controller.js

import {Controller} from '@hotwired/stimulus'
import axios from 'axios'

/* stimulusFetch: 'lazy' */
export default class extends Controller {
  connect() {
    const addressInput = this.element
      .closest('form')
      .querySelector('[name$="[address]"]')

    if (!addressInput) {
      return
    }

    this.element.addEventListener('blur', () => {
      addressInput.disabled = true
      ;(async () => {
        try {
          const res = await axios.get(`/some/api?zipCode=${this.element.value}`)
          addressInput.value = res.data
        } finally {
          addressInput.disabled = false
        }
      })()
    })
  }
}

こんな感じで実装してみました。

/* stimulusFetch: 'lazy' */ というコメントは、自分を data-controller 属性で指定している要素がいないページではJSファイルが読み込まれなくなるためのオプションです。

ドキュメント:https://github.com/symfony/stimulus-bridge#lazy-controllers

2. EasyAdminのFieldにStimulusコントローラの処理を適用

あとはこのStimulusコントローラをEasyAdminのFieldに当てがうだけです。

use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class FooCrudController extends AbstractCrudController
{
    // ...
    
    public function configureFields(string $pageName): iterable
    {
        // ...
        
        yield Field::new('zipCode')
            ->setFormTypeOption('attr', [
                'data-controller' => 'zipCode',
            ])
            ->addWebpackEncoreEntries('app')
        ;
        
        yield Field::new('address');
        
        // ...
    }
}
  • setFormTypeOption(/* 略 */) でフォームフィールドに data-controller="zipCode" を付加
  • addWebpackEncoreEntries('app')app エントリーのアセットを読み込むよう指示

しているだけです。

これで、EasyAdminの管理画面上で郵便番号からの住所補完を実装することができました🙌

GitHubで編集を提案

Discussion