前回まででブロックをいくつか作ってみたのだが、今回は情報の保存先という点について詳しく触れてみたい。
HTMLの属性・中身に情報を保存する
インタラクティブなHTML要素というのはそれほど多くない。テーマと管理画面で同じinput要素を表示する必要性はほぼないだろうが、ブロックの情報保存先としてわかりやすいので、まずこれから触れてみよう。
inputというブロックを用意し、inputタグをテーマ側にそのまま表示することとしよう。とりあえずブロックcapital-block-inputをPHPで登録し……
// Register block.
add_action( 'init', function() {
// Register JS
wp_register_script( 'capital-block-input', CAPITAL_BLOCK_ASSET_URL . 'assets/js/inputs.js', [ 'wp-element', 'wp-blocks' ], CAPITAL_BLOCK_VERSION, true );
// Register block.
if ( defined( 'GUTENBERG_VERSION' ) ) {
// Alert Block.
register_block_type( 'capital-block/input', [
'editor_script' => 'capital-block-input',
] );
}
});
続いて、UIを提供するJSを記述する。
const {registerBlockType} = wp.blocks;
const inputStyle = {
width: '100%',
};
registerBlockType('capital-block/input', {
title: 'Input',
icon: 'edit',
category: 'formatting',
attributes: {
string: {
type: 'string',
source: 'attribute',
selector: 'input',
attribute: 'value'
},
},
edit({attributes, setAttributes}) {
return (
<input type='text' value={attributes.string} style={inputStyle}
onChange={(event) => setAttributes({string: event.target.value})}/>
);
},
save({attributes}) {
return (
<input type='text' value={attributes.string} />
);
},
});



この場合、ポイントとなるのは、attribute > stringのsourceとselectorである。selectorに指定された場合、該当するタグが選択対象となる。ではそのタグの何を利用するのかというと、sourceにattributeを指定しているので属性を使う。今回はinputタグを利用しているので、そのvalue属性を利用するというわけだ。
なお、この記述では、saveとeditメソッドにまったく同じinputタグが使われているためこのような記述になっている。入力UIではinputを使いつつも、表示するものが例えばpタグならば、selectorはpとする必要がある。要するに、attributeのsourceとは、「保存されたタグを編集用に復元するための方法」を記述するプロパティなのだ。
もしtextareaを使いたいのであれば、sourceをhtmlにする必要がある。textareaはその他のinput要素と異なり、value属性を持たないからだ。
add_action( 'init', function() {
// Register JS
wp_register_script( 'capital-block-textarea', CAPITAL_BLOCK_ASSET_URL . 'assets/js/textarea.js', [ 'wp-element', 'wp-blocks' ], CAPITAL_BLOCK_VERSION, true );
// Register block.
if ( defined( 'GUTENBERG_VERSION' ) ) {
// Alert Block.
register_block_type( 'capital-block/textarea', [
'editor_script' => 'capital-block-textarea',
] );
}
} );
const {registerBlockType} = wp.blocks;
const inputStyle = {
width: '100%',
padding: '10px',
'box-sizing': 'border-box'
};
registerBlockType('capital-block/textarea', {
title: 'TextArea',
icon: 'edit',
category: 'formatting',
attributes: {
string: {
type: 'string',
source: 'text',
selector: 'textarea',
},
},
edit({attributes, setAttributes}) {
return (
<textarea style={inputStyle} rows='3' onChange={(event) => setAttributes({string: event.target.value})}>{attributes.string}</textarea>
);
},
save({attributes}) {
return (
<textarea style={inputStyle} rows='3'>{attributes.string}</textarea>
);
},
});


ちなみにstyle属性を利用すると、CSSを管理画面で保存することができてしまうが、ブラウザ互換性などを考えると結局外部CSSを登録する羽目になるだろう。また、テーマのデザインが変更になった場合はこのstyle属性が邪魔になる。Scoped CSSなどを使う場合、「テーマの変更」という問題は避けて通れないだろう。
リッチテキスト
Gutenbergのようなエディタを利用する場合、当然だがデザインを施されたコンポーネントを直接編集できるようにしたいだろう。その場合は前回と同じくリッチテキストコンポーネントを登録する必要がある。リッチテキストコンポーネントが他と異なるのは、typeにarray、sourceにchildrenを指定する点だ。前回書いた通り、リッチテキストは複数のDOMの配列と解釈される。
const { registerBlockType } = wp.blocks;
const { RichText } = wp.editor;
registerBlockType( 'capital-block/richtext', {
title: 'RichText',
icon: 'edit',
category: 'formatting',
attributes: {
content: {
type: 'array',
source: 'children',
selector: 'div',
}
},
edit({attributes, setAttributes}) {
return (
<RichText
tagName="div"
onChange={ (content) => setAttributes({content: content}) }
value={attributes.content}
/>
);
},
save({attributes}) {
return (
<RichText.Content
tagName={'div'}
value={attributes.content}/>
);
},
} );



カスタムフィールド
さて、これまでのブロックはすべて、投稿本文に保存するデータとそのUIを提供するブロックだった。しかし、カスタムフィールドにデータを保存したい場合はどうすればよいのだろうか? たとえば、日本のご当地ネタあるあるをまとめているサイトを考えてみよう。「その都道府県にしかない体操あるある」という記事を作成し、あるあるが10件登録されているとする。そのうち1つは「千葉県のなのはな体操」というブロックだったとしよう。そのブロックの記事内容はともかくとして、ブロックに「千葉県」というカスタムフィールドが付与されていたら、meta_queryを使った検索などで「千葉県について書いている記事一覧」を提供できるだろう。
前置きが長くなったが、このためにはブロック属性のsourceにmetaを指定する必要がある。
const {registerBlockType} = wp.blocks;
const prefectures = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県','茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県','新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県','鳥取県','島根県','岡山県','広島県','山口県','徳島県','香川県','愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県','大分県','宮崎県','鹿児島県','沖縄県'];
registerBlockType('capital-block/meta', {
title: 'Meta',
icon: 'generic',
category: 'formatting',
attributes: {
prefecture: {
type: 'string',
source: 'meta',
meta: 'prefecture' // ここの値はカスタムフィールド名
},
},
edit({attributes, setAttributes}) {
return (
<select onChange={(event) => setAttributes({prefecture: event.target.value})}>
{prefectures.map((pref) => {
return (
<option value={pref} selected={pref === attributes.prefecture}>{pref}</option>
)
})}
</select>
);
},
save() {
return null;
},
});
これだけではダメで、register_metaという関数を用い、PHP側でそのカスタムフィールドをアクセス可能にする必要がある。また、今回はrender_callackを用い、その都道府県の地図を表示してみよう。
add_action( 'init', function() {
// Register JS.
wp_register_script( 'capital-block-meta', CAPITAL_BLOCK_ASSET_URL . 'assets/js/meta.js', [ 'wp-element', 'wp-blocks' ], CAPITAL_BLOCK_VERSION, true );
if ( defined( 'GUTENBERG_VERSION' ) ) {
// Register block.
register_block_type( 'capital-block/meta', [
'editor_script' => 'capital-block-meta',
'render_callback' => function( $attributes, $content = '' ) {
// Get post meta.
$pref = get_post_meta( get_the_ID(), 'prefecture', true );
$src = add_query_arg( [
'key' => GOOGLE_MAP_EMBED_KEY,
'q' => rawurlencode( $pref ),
'zoom' => 16,
], 'https://www.google.com/maps/embed/v1/place' );
return <<<HTML
<iframe class="event-map-iframe" src="{$src}" frameborder="0" style="width: 100%" height="300"></iframe>
HTML;
},
] );
// Register meta
register_meta( 'post', 'prefecture', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
) );
}
} );




ちなみに、カスタムフィールドのsingle => trueを設定すると、何個ブロックを追加しても自動的に内容が同期されるようになる。これはReactを一度でも書いたことがある人なら、「Gutenbergやるじゃん!」という感想を抱くはずだ。
まとめ
というわけで、カスタムフィールドを含めた高度な内容について今回は触れてみた。他にあると便利そうな機能としては、インクリメンタルサーチがある。たとえば、他の投稿やタクソノミー、ユーザーを選ぶときに、ある程度いい感じのインクリメンタルサーチがあると便利だというのは想像に難くないだろう。しかし、このAPIはまだ未整備でドキュメントが作られていないので、おいおい触れていきたい。
最後になるが、有料会員向けにソースコードを提供して終わりとする。
続きの 4% を読み、添付されたファイルにアクセスするには、Gumroadでライセンスキーを取得してください!

コメントを残す