ダイナミックブロックとは
通常のブロックだとブロックエディタから入力したテキストは静的に本文の一部として保存され、表示時にも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'];
}
ここまででブロックの登録とダイナミックブロック化、入力して保存、記事への表示まで完了したはず。
長くなったので次の記事で記事表示部分を試します。
参考記事
全体的に以下の記事を踏襲して学習を進めています。
コードについてはコピペして試し、自分の環境で動かしたものを本記事にて書いています。