WPダイナミックブロック作成|保存して表示まで|WordPress|GutenBerg

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

通常のブロックだとブロックエディタから入力したテキストは静的に本文の一部として保存され、表示時にもHTMLとして静的にレンダリングされる。

保存される本文をコードエディタで見るとこんな感じ。

<!-- wp:paragraph -->
<p>ああああ</p>
<!-- /wp:paragraph -->

これを、パラメータとして保存して、レンダリング時に動的に吐き出すような仕組みとして埋め込むことができ、それをダイナミックブロックと呼ぶ。

こんな感じで保存される。

<!-- wp:create-block/block-sample {"myTitle":"テストです","myContent":"\u003cp\u003eテスト本文です\u003c/p\u003e"} /-->

まずはカスタムブロック作成

順に学習するとしてまずはカスタムブロックを静的に作成する。

今回はプラグインとしてカスタムブロックを作成できるチュートリアルであるcreate-blockを使用する。

前提として、ローカルでWordPressをセッティングして、そのプラグインフォルダにて作業を行うものとする。

ターミナルでプラグインフォルダに移動してnpxでcreate-blockを引数無しで実行すると、対話形式でのインストールが始まる。

$ cd プラグインフォルダ
$ npx @wordpress/create-block

ここではとりあえずプラグインのスラッグ(The block slug used for identification/フォルダ名にも使用される)と画面に表示されるブロック名(The display title for your block)だけ自分がわかりやすいものに変えて指定する。ここではそれぞれblock-sample、Block Sampleとした。

ブロックカテゴリをtextにしておけばとりあえず試すときに上の方に表示されて便利。

インストールが完了すると、以下の構成でファイルが生成されている。

block-sample

block-sample.php

block.json

build

node_modules

package-lock.json

package.json

readme.txt

src

edit.js

editor.scss

index.js

save.js

style.scss

src以下がブロックの詳細として機能する部分。

各ファイルの大まかな役目を整理すると以下の通り。

index.jsブロックの起点となるjsファイル。
当てるスタイル、編集画面のUI、保存処理を指定する。
edit.js編集画面のUIを定義したファイル。
save.js保存時の処理を定義したファイル。

この時点で管理画面を確認すると指定した名前でプラグインができているので、有効化するとデフォルトの静的なブロックが表示されているはず。

ターミナルでblock-sampleに移動してnpm startすれば開発環境が起動して、逐一変更が反映される状態となる。

$ cd block-sample
$ npm start

カスタムブロックを編集可能ブロックに変更

属性(入力項目)としてタイトルと本文を追加する。

index.js

registerBlockTypeに以下の内容を追加。

  //入力された値を保存するための属性を設定
  attributes: {
    //タイトル(h3)の内容を保持するための属性
    myTitle: {
      type: 'string',
      default: '',
      source: 'html',
      selector:'.myRichTextTitle' 
    },
    //本文(p)の内容を保持するための属性
    myContent: {
      type: 'array',
      default: '',
      source: 'children',
      selector:'.myRichTextContent' 
    },
  },

出来上がりこんな感じ。

import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';

registerBlockType( 'create-block/block-sample', {
  	attributes: {
    	myTitle: {
			type: 'string',
			default: '',
			source: 'html',
			selector:'.myRichTextTitle'
	    },
		myContent: {
			type: 'array',
			default: '',
			source: 'children',
			selector:'.myRichTextContent'
		},
	},
	edit: Edit,
	save,
} );

edit.js

RichTextのコンポーネントをimport

import { RichText } from '@wordpress/block-editor';

propsを分割代入

export default function Edit( props ) {
  const { attributes: { myTitle, myContent}, setAttributes } = props;

returnをRichTextからの変数で生成した内容に変更。

  return (
    <div className={ className }  >
      <RichText 
        className='myRichTextTitle'
        value={ myTitle }
        onChange={ (newTitle) => setAttributes({ myTitle: newTitle }) }
        tagName='h3'
        placeholder= 'タイトルを入力' 
        keepPlaceholderOnFocus={true}
      />
      <RichText
        className='myRichTextContent'
        value={ myContent }
        onChange={ (newContent) => setAttributes({ myContent: newContent }) }
        tagName='div'
        multiline= 'p'
        placeholder= '文章を入力' 
      />
    </div>
  );

classNameあたりはサンプルで記述されていたuseBlockProps活かしで、propsからの値設定を追加して、出来上がりこんな感じ。

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
import { RichText } from '@wordpress/block-editor';

export default function Edit(props) {
	const { attributes: { myTitle, myContent}, setAttributes } = props;

	return (
		<div { ...useBlockProps() }>
			<RichText
				className="myRichTextTitle"
				value={myTitle}
				onChange={(newTitle) => setAttributes({ myTitle: newTitle })}
				tagName="h3"
				placeholder="タイトルを入力"
				keepPlaceholderOnFocus={true}
			/>
			<RichText
				className="myRichTextContent"
				value={myContent}
				onChange={(newContent) => setAttributes({ myContent: newContent })}
				tagName="div"
				multiline="p"
				placeholder="文章を入力"
			/>
		</div>
	);
}

save.js

RichTextのコンポーネントをimport

import { RichText } from '@wordpress/block-editor';

propsを分割代入

export default function Edit( props ) {
  const { attributes: { myTitle, myContent} } = props;

保存処理

  return (
    <div>
      <RichText.Content
        className='myRichTextTitle'
        value={ myTitle }
        tagName='h3'
      />
      <RichText.Content
        className='myRichTextContent'
        value={ myContent }
        tagName='div'
      />
    </div>
  )

出来上がり

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import { RichText } from '@wordpress/block-editor';

export default function save(props) {
	const { attributes: { myTitle, myContent} } = props;

	return (
		<div { ...useBlockProps.save() }>
			<RichText.Content
				className="myRichTextTitle"
				value={myTitle}
				tagName="h3"
			/>
			<RichText.Content
				className="myRichTextContent"
				value={myContent}
				tagName="div"
			/>
		</div>
	);
}

ここまでで通常ブロックの編集可ブロックの設定が完了。

次の項にてこれをダイナミックブロックに変更。

ダイナミックブロックに変更

ダイナミックブロックではデータはデータベースに保存されず、ブロックの属性のみが保存されます。なのでsaveの処理を割愛すべく、nullを返すようにします。

export default function save() {
  return null;
}

上記のようにsave.jsの中でnullを返してもいいんですが、これだけの処理であればindex.jsにnullを返す処理を書いちゃってもいいみたいです。

末尾あたりのsaveにnullを返す処理を加えます。

また、attributesにsourceプロパティを設定しているとデータをsave.jsの返り値から取得しようとするため、コメントアウトします。sourceプロパティが無いとarrayは機能しないとのことで、typeがarrayのものはstringに変更。

ということで、まとめて以下のように変更します。

import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
// import save from './save';

registerBlockType( 'create-block/block-sample', {
  	attributes: {
    	myTitle: {
			type: 'string',
			default: '',
			// source: 'html',
			selector:'.myRichTextTitle'
	    },
		myContent: {
			type: 'string',
			default: '',
			// source: 'children',
			selector:'.myRichTextContent'
		},
	},
	edit: Edit,
	save: () => { return null },
} );

ここまでで、入力と保存、編集画面への表示が実装されているはず。

そしてこのままだと表示画面に出力されないので、プラグインフォルダのルートに格納されているプラグインPHPファイル(今回はblock-sample.php)に書き出し関数を記述し、register_block_typeの第2引数のarrayにrender_callbackというキーで設定します。

function create_block_block_sample_block_init() {
	register_block_type(
		__DIR__,
		array(
			'render_callback' => 'block_sample_render',
		)
	);
}
add_action( 'init', 'create_block_block_sample_block_init' );

function block_sample_render($attr, $content) {
  return $attr['myTitle'];
}

ここまででブロックの登録とダイナミックブロック化、入力して保存、記事への表示まで完了したはず。

長くなったので次の記事で記事表示部分を試します。

参考記事

全体的に以下の記事を踏襲して学習を進めています。

コードについてはコピペして試し、自分の環境で動かしたものを本記事にて書いています。