前回まででブロックをいくつか作ってみたのだが、今回は情報の保存先という点について詳しく触れてみたい。
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でライセンスキーを取得してください!
コメントを残す