Before Gutenberg – ブロックの入れ子InnerBlockの作成

GutenbergにはInnerBlockという仕組みがあり、ブロックを内包するブロックを作成することができる。InnerBlockは次のような特徴を持つ。

  • 内包されるブロック(子ブロック)を指定できる。
  • 編集の可否を選べる。

また、各ブロックは「親」を指定することができ、特定のブロックの中にしか入らないブロックを作成することもできる。

たとえば、「カートに入れる」ボタンを考えてみよう。このボタンをどの文脈とも関係ないブロックに追加できてもしょうがない。その場合、たとえば woocommerce/product ブロックの中にだけ表示できるというような制限ができるとわかりやすいだろう。

今回はdl(定義リスト・説明リスト)ブロックを作成することで、この仕組みを覚えてもらいたい。

作成するブロック

さて、JSXなどの変換はすべてできていると仮定し、dl,dt, ddの3つのブロックを作成する。dtdddlの中以外で使うことはないので、「子ブロック」としてはうってつけだろう。まずはPHPから一気に登録する。それぞれのJSがブロックに対応すると考えてもらいたい。

// $this->assets は各アセットへのパス、
// self::VERSION はプラグインバージョン。
add_action( 'init', function() {
	// Register DL asset.
	wp_register_script( 'wp-yomigana-dl', $this->assets . '/js/dist/definition-list.js', [ 'wp-blocks', 'wp-editor' ], self::VERSION, true );
	wp_register_style( 'wp-yomigana-dl', $this->assets . '/css/editor-dl.css', [], self::VERSION );
	// Register dt asset.
	wp_register_script( 'wp-yomigana-dt', $this->assets . '/js/dist/definition-term.js', [ 'wp-blocks', 'wp-editor' ], self::VERSION, true );
	// Register dd asset.
	wp_register_script( 'wp-yomigana-dd', $this->assets . '/js/dist/definition-description.js', [ 'wp-blocks', 'wp-editor' ], self::VERSION, true );
	register_block_type( 'wp-yomigana/dl', [
		'editor_style'  => 'wp-yomigana-dl',
		'editor_script' => 'wp-yomigana-dl',
	] );
	register_block_type( 'wp-yomigana/dt', [
		'editor_script' => 'wp-yomigana-dt',
	] );
	register_block_type( 'wp-yomigana/dd', [
		'editor_script' => 'wp-yomigana-dd',
	] );
} );

それでは、各ブロックの実装へ移ろう。まず、dlブロックだが、これは中身にInnerBlocksだけを保持する。

const { registerBlockType } = wp.blocks;
const { InnerBlocks } = wp.editor;

registerBlockType( 'wp-yomigana/dl', {

  title: 'Definition List',

  icon: '',

  category: 'common',

  keywords: [],

  edit({attributes, className}){
    // 許可されるブロックを登録
    const allowedBlocks = [ 'wp-yomigana/term', 'wp-yomigana/description' ];
    return (
      <div className={className}>
        <InnerBlocks allowedBlocks={allowedBlocks} templateLock={false} />
      </div>
    )
  },

  save({className}){
    return (
      <dl className={className}>
        <InnerBlocks.Content />
      </dl>
    )
  }
} );

InnerBlocksはRichTextと似ており、中身を保存するときにInnerBlocks.Contentを返す。編集中に許可されるブロックを allowedBlocks属性で指定することができ、また、templateLockfalseにすることで、ユーザーが自由にブロックを追加・削除できる。もちろん、編集ロックして、特定のテンプレートしか入稿できないようにすることも可能だ。

それでは、続いてdtブロックを作成しよう。こちらはparentプロパティによって、「どのブロックの子ブロックか」を明示的に宣言する。これにより、定義リストの中にのみ表示される。

const { registerBlockType } = wp.blocks;
const { RichText } = wp.editor;

registerBlockType( 'wp-yomigana/term', {

  title: 'Term',

  icon: '',

  category: 'common',

  // 親ブロックを指定
  parent: [ 'wp-yomigana/dl' ],

  attributes: {
    content: {
      source: 'html',
      selector: 'dt'
    }
  },

  edit({attributes, setAttributes, className}){
    return (
      <RichText className={className} tagName='div' value={attributes.content} onChange={(content)=>setAttributes({content})}/>
    );
  },

  save({attributes}){
    return (
      <RichText.Content tagName='dt' value={attributes.content} />
    )
  }

} );

dtもほとんど同じなので、内容は割愛する。完成するのがこんな感じのブロックである。

挿入できるのはdtとddだけというブロックができた。

次回以降、もう少し複雑な内容にしてTemplate Blockを作成してみたい。

以下、有料会員向けにソースコードと実際のコーディング動画をお届けする。

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

コメントを残す

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