Menu


@wordpress/components FormTokenField のサジェストにカスタム投稿のタイトルをセットする

2024年01月07日

WordPress ブロックエディタのサイドバーにカスタム投稿のタイトルを入力し、入力している文字からカスタム投稿の候補を取得(サジェスト)、取得した候補をクリックするとカスタム投稿が選択されるブロックが自作できたらいいなと思い調査を開始。

WordPress のコンポーネントを色々と見ていると、FormTokenField というコンポーネントには suggest 機能が備わっており、利用しやすいかもと気が付きます。

それから FormTokenField post title suggest などで調べていると、GitHub Gist にて Gutenberg FormTokenField block with posts as source というソースコードを発見。

このソースコードを読み進めていくと、今回やりたいと思った内容を実現できそうな気がしましたので、このソースコードを参考にしつつ、 edit.js を以下のとおりに記述してみました。

※ edit.js 以外のファイル( block.json や render.php )については今回は割愛します。

import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import {
  useBlockProps,
  InspectorControls
} from '@wordpress/block-editor';
import {
  FormTokenField,
  PanelBody
} from '@wordpress/components';
 
export default function Edit( { attributes, setAttributes } ) {
  const blockProps = useBlockProps();
  
  const {
	selectedPosts
  } = attributes;
  
  const posts = useSelect( ( select ) =>
	select( 'core' ).getEntityRecords( 'postType', 'plan', {per_page: -1} )
  );
  
  let postNames = [];
  let postsFieldValue = [];
  
  if ( posts !== null ) {
    	  
	postNames = posts.map( ( post ) => post.title.rendered );
	
	postsFieldValue = selectedPosts.map( ( postId ) => {
	  let wantedPost = posts.find( ( post ) => {
	    return post.id === postId;
	  } );
	  if ( wantedPost === undefined || ! wantedPost ) {
	    return false;
	  }
	  return wantedPost.title.rendered;
	} );
	
  }
  return (
    <div { ...blockProps }>
      <InspectorControls>
        <PanelBody title={ __( '投稿を取得', 'text-domain' ) } initialOpen="false">
		  <FormTokenField
		    label={__( '投稿名を入力してください', 'text-domain' )}
		    value={ postsFieldValue }
		    suggestions={postNames}
		    onChange={ ( selectedPosts ) => {
							
		      let selectedPostsArray = [];
		      selectedPosts.map(
		        ( postName ) => {
		          const matchingPost = posts.find( ( post ) => {
		            return post.title.rendered === postName;
		          } );
		          if ( matchingPost !== undefined ) {
		            selectedPostsArray.push( matchingPost.id );
		          }
		        }
		      )
		      setAttributes( { selectedPosts: selectedPostsArray } );
		    } }
		  />
        </PanelBody>
      </InspectorControls>
    </div>
  );
}

この edit.js を含むブロックのプロジェクトフォルダで npm run build を実行し、WordPress のエディタでブロックを追加してみると、入力している文字からカスタム投稿の候補を取得(サジェスト)、取得した候補をクリックするとカスタム投稿が選択されるブロックが出来上がりました。

@wordpress/components FormTokenField カスタム投稿をサジェストしている図

FormTokenField の suggestions は候補に出したい文字の配列を渡してあげれば良いので、割と直感的にソースを書くことができました。

上記の例では、getEntityRecords にてカスタム投稿タイプ plan の投稿を全件取得し posts に代入、posts の投稿データを基に、FormTokenField suggestions 用の postNames、FormTokenField value 用の postsFieldValue などにそれぞれ値をセットしています。

block.json の attributes にセットした配列 selectedPosts には、選択したカスタム投稿の post_id が代入されていきますので、render.php(コールバック用のPHPファイル)で get_the_title や get_the_permalink などの関数も扱いやすいかと思います。

WordPress 公式の情報だけではなかなか理解しにくいブロック開発ですが、コンポーネント名とやりたい事を英語で検索してみると、探している情報にもリーチしやすくなるかもしれません。

ちなみに、今回はカスタム投稿タイプ plan を例にしていますが、通常の投稿を取得する場合は plan を post にすれば動作するかと思います。

WordPress のブロック開発の構文はまだまだ慣れませんが、少しずつ React ( JSX ) のお作法も理解が進んでいるような、いないような、、、?

引き続き、WordPress ブロック開発のお勉強を進めようと思います。

以下は、今回の記事を作成するにあたって参考にしたサイトです。

参考情報
Gutenberg FormTokenField block with posts as source · GitHub
FormTokenField – @wordpress/components

広告