Before Gutenberg – ダイナミックブロック入門

前回はシンプルなアラートボックスを作成したが、今回は外部要因によって動的に中身が変更されるダイナミックブロックに挑戦してみよう。

ダイナミックブロックとは?

PHPによる動的な生成を伴うものである。保存される内容=表示される内容でよいのなら以前のやり方でよいが、たとえば、「最新の投稿リスト」のようなものの場合、その内容は変わっていく。

今回は「x年y月のイベント一覧を表示するブロック」という想定をしよう。条件は次の通り。

  • 沢山のイベントがカスタム投稿タイプeventとして登録されている。
  • 各イベントは開催日(_event_date)、会場の緯度(_lat)および経度(_lng)をカスタムフィールドに持つ。
  • Gutenbergでブロックに年yearおよび月monthを指定すると、その時期に開催されるイベントの一覧が出力される。

それでは、早速とりかかろう。今回表示するブロックのイメージは次の通り。

完成形を先にHTMLで作っておいた。

ブロックの登録

前回と同じく、まずは、必要なアセットとブロックをPHPから次のようにして登録する。時間の節約のため、CSSの内容はすでに完成しているものとする。

/**
 * Register event and block assets.
 */
add_action( 'init', function() {
  // Register CSS & JS.
  wp_register_style( 'capital-block-event', CAPITAL_BLOCK_ASSET_URL . 'assets/css/event.css', [], CAPITAL_BLOCK_VERSION );
  wp_register_script( 'capital-block-event', CAPITAL_BLOCK_ASSET_URL . 'assets/js/event.js', [ 'wp-element', 'wp-blocks' ], CAPITAL_BLOCK_VERSION, true );
  // Register block.
  if ( defined( 'GUTENBERG_VERSION' ) ) {
    register_block_type( 'capital-block/event', [
      'editor_style'    => 'capital-block-event',
      'editor_script'   => 'capital-block-event',
    ] );
  }
} );

続いて、JSの中身を書いていこう。今回のダイナミックブロックでは、saveメソッドを定義しない。実際のレンダリングはPHPで行うからだ。editメソッドはとりあえず罫線(hr)を出力しておこう。

const { registerBlockType } = wp.blocks;


registerBlockType( 'capital-block/event', {

  title: 'Event',

  icon: 'calendar-alt',

  category: 'embed',

  attributes: {
    year: {
      type: 'integer',
    },
    month: {
      type: 'integer',
    },
  },

  edit( {attributes, setAttributes} ) {
    return <hr />
  },

  save(){
    return null;
  }

} );

以上で、とりあえず罫線が表示されるブロックが出力されるはずである。

まずはボタンの表示から。Eventというボタンが出ている。

編集UIの作成

それでは、編集UIの作成をしよう。今回は年月を指定するプルダウンを作成する。

registerBlockType( 'capital-block/event', {
  edit( {attributes, setAttributes} ) {
    const years = [];
    for(let i = 0; i < 20; i++){
      years.push( 2016 + i );
    }
    const months = [];
    for(let i = 1; i <= 12; i++){
      months.push(i);
    }
    return (
      <div className='event-editor'>
        <select onChange={ (event) => { setAttributes({year: event.target.value}) } }>
          {years.map( (year) => {
            return (
              <option value={year} selected={year == attributes.year}>{year}年</option>
            )
          } )}
        </select>
        <select onChange={ (event) => { setAttributes({month: event.target.value}) } }>
          {months.map( (month) => {
            return (
              <option value={month} selected={month == attributes.month}>{month}月</option>
            )
          } )}
        </select>
        <hr/>
      </div>
    );
  },
} );

ポイントとしては、Reactにはループの制御構文がないので、Array.mapを利用して反復処理を行っている点。詳細はReactでの配列ループ利用方法をおさらいするなどを参考にしてほしい。これで年月を選択して保存すると、実際に保存されるデータは次のようになる。

<!-- wp:capital-block/event {"year":"2018","month":"7"} /-->

さて、この記事を表示してみても何も表示されない。コメントしかないからだ。そこで、render_callbackを登録して、描画関数をPHPに書く。

register_block_type( 'capital-block/event', [
	'editor_style'    => 'capital-block-event',
	'editor_script'   => 'capital-block-event',
	'render_callback' => function( $attributes, $content = '' ) {
		$attributes = wp_parse_args( $attributes, [
			'year'  => 0,
			'month' => 0,
		] );
		return capital_block_render_event( $attributes['year'], $attributes['month'] );
	},
] );

今回は$year$monthを渡すと当該月のイベントリストを表示する自作関数capital_block_render_eventを利用している。ここまでで次のようにテーマ側できちんと表示されているはずだ。

当該月のイベント一覧が表示されている。

テーマと管理画面での見栄えを一致させる

さて、現状のUIだと、年月を指定するたびにそれがどのような見栄えになるのかをプレビューしなければならない。そこで、PHPによる描画結果を管理画面でも見たいものだ。そのためのAPIがServerSideRenderである。

これはReactがREST APIを利用して、PHPによる描画結果を生成するものだ。JS側で早速この処理を書いてみよう。attributesとブロック名を渡すだけで描画してくれる優れものだ。attributesの変更も検知し、自動でUIを更新してくれる。

const { registerBlockType } = wp.blocks;
const { ServerSideRender } = wp.components;

registerBlockType( 'capital-block/event', {
  edit( {attributes, setAttributes} ) {
    // 中略
    return (
      <div className='event-editor'>
        // 中略
        <hr/>
        <ServerSideRender
          block="capital-block/event"
          attributes={ attributes }
        />
      </div>
    );
  },
} );

ただし、これだけだとまだ動かない。PHP側にどのような属性を受け入れるのかを支持する必要がある。これはregister_block_type関数で行うことができる。

register_block_type( 'capital-block/event', [
	'editor_style'    => 'capital-block-event',
	'editor_script'   => 'capital-block-event',
	'attributes'      => [
		'year'  => [
			'type' => 'integer',
		],
		'month' => [
			'type' => 'integer',
		],
	],
	'render_callback' => function( $attributes, $content = '' ) {
		$attributes = wp_parse_args( $attributes, [
			'year'  => 0,
			'month' => 0,
		] );
		return capital_block_render_event( $attributes['year'], $attributes['month'] );
	},
] );

これでプルダウンを変更するたびイベントのリストが更新されるようになった。

属性を変更すると、ぐるぐる回ってUIが更新される。

まとめ

ダイナミックブロックによるサーバーサイドレンダリングはあくまでフォールバックであり、公式に推奨されない方法だそうだ。しかし、Shortcakeと同じく、WYSIWYGを提供する機能として便利なので、しばらくは使われることだろう。APIとJSをわけるコーディングより労力が少ないのも嬉しいポイントだ。

以下、有料会員向けにソースコード全体とコーディング動画を提供する。

続きの 4% を読み、添付されたファイルにアクセスするには、Gumroadでライセンスキーを取得してください!

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください