33
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Wordpress Gutenberg よく使いそうなコンポーネントまとめ

Last updated at Posted at 2018-08-26

#この記事は?

Wordpressの新エディタGutenbergをいじってて
よく使いそうだと思ったコンポーネントをまとめていきます
追記編集していきます

TextControl と TextareaControl

テキスト編集のコンポーネント。
onChangeでイベントオブジェクトじゃなく中身の文字列だけが渡されるようになってるので、値の取り出しとかしなくていいので普通にtextareaとか書いちゃうより楽です。

JSX

const {TextControl, TextareaControl} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<TextControl
				onChange={(newText1)=>setAttributes({text1: newText1});}
			/>,
			<TextareaControl
				onChange={(newText2)=>setAttributes({text2: newText2});}
			/>
		];
	}
);

RichText

ちょっとした文字装飾ができるテキスト編集のコンポーネント。
使い方は基本TextControlと同じなのだけどこいつはwp.componentsではなくwp.editorにいます。

JSX

const {RichText} = wp.editor;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<RichText
				onChange={(newText)=>setAttributes({text: newText});}
			/>
		];
	}
);

RichTextで各文字に適用できる文字スタイルは
registerFormatTypeで増やすことができます

以下smallを追加してみるコード

const {Fragment}=wp.element;
const {RichText,RichTextToolbarButton,RichTextShortcut} = wp.editor;
const {registerFormatType,toggleFormat}=wp.richText;
const {__}=wp.i18n;

registerFormatType('my/editor',{
	title:'small',
	tagName:'small',
	className:null,
	edit({isActive,value,onChange}){
		const onToggle=()=>onChange(toggleFormat(value,{type:'catpow/small'}));
		
		const icon=(
			<svg role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" aria-hidden="true">
				<path d="M5.6,16.7l3.6-9.4h1.3l3.8,9.4H13l-1.1-2.8H8l-1,2.8H5.6z M8.3,12.9h3.2l-1-2.6C10.2,9.5,10,8.9,9.9,8.4
		C9.7,9,9.6,9.6,9.3,10.1L8.3,12.9z"/>
			</svg>
		);

		return [
			<Fragment>
				<RichTextShortcut
					type={'primary'}
					character={'-'}
					onUse={onToggle}
				/>
				<RichTextToolbarButton
					icon={icon}
					title={'small'}
					onClick={onToggle}
					isActive={isActive}
					shortcutType={'primary'}
					shortcutCharacter={'-'}
				/>
			</Fragment>
		];
	}
});

iconにはdash-iconの名前(リンク先で書かれてる名称の"dashicon-"より後ろ)で指定する他にSVGを使うこともできます

RichTextShortcutのtypeの指定はそれぞれ以下のように修飾キーに対応

Mac Win
primary [ COMMAND ] [ CTRL ]
primaryShift [ SHIFT, COMMAND ] [ CTRL, SHIFT ]
primaryAlt [ ALT, COMMAND ] [ CTRL, ALT ]
secondary [ SHIFT, ALT, COMMAND ] [ CTRL, SHIFT, ALT ]
access [ CTRL, ALT ] [ SHIFT, ALT ]
ctrl [ CTRL ] [ CTRL ]
alt [ ALT ] [ ALT ]
ctrlShift [ CTRL, SHIFT ] [ CTRL, SHIFT ]
shift [ SHIFT ] [ SHIFT ]
shiftAlt [ SHIFT, ALT ] [ SHIFT, ALT ]

RichTextの値はsaveでの出力の際には<RichText.Content value={value}/>のようにして出力しなくてはなりません。WP5.4以前はTextControlとかと同じノリで{value}と書いても解決してくれましたが、WP5.5以降はちゃんと書かなくてはいけなくなりました。

CheckboxControl

チェックボックスのコンポーネント
多分一番使ってるコンポーネント
チェックボックスをポチポチするだけで
要素を入れたり消したりできるのはユーザー的に便利

JSX

const {RangeControl} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<CheckboxControl
				label='真偽値'
				help={bool?'':''}
				onChange={(bool)=>{setAttributes({bool:bool});}}
				checked={bool}
			/>
		];
	}
);

RangeControl

スライダーで数値の入力できるコンポーネント
ユーザー入力を特定の範囲の数値に保証できるのがいいところ
こういうこと簡単にできるのは便利

JSX

const {RangeControl} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<RangeControl
				label='数値'
				onChange={(number)=>{setAttributes({number:number});}}
				value={number}
				min={0}
				max={12}
			/>
		];
	}
);

ServerSideRender

php側のregister_block_typeでrender_callbackを指定して
サーバーサイドでレンダリングするように作られたブロックをプレビューするコンポーネント。
使い方とかは公式ハンドブックのCreating dynamic blocksで大体わかります、大体だけ。
要は編集画面上で検索とかサーバーサイドの処理が絡むようなものをプレビューしながら編集できるわけです。

フォームの埋め込みなどショートコードでやってたことをもっと直感的にできるようになるわけですが、だからと言ってショートコードの出番がなくなるわけでもありません。
ショートコードにはテキストの途中の任意の場所で使用できるという利点があります。

また、ショートコードはブロックのレンダリングより後に行われるので、ブロックにショートコードを含むコードを出力させることで、ショートコードを組み合わせたり再利用したブロックというのも実現します。

JSX

//const {ServerSideRender} = wp.components; 
const {serverSideRender:ServerSideRender}=wp;


registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<ServerSideRender
				block='myPlugin/myBlock'
				attributes={attributes}
			/>
		];
	}
);

注意点としてはattributesの設定をjs側ではなくphp側
つまりregister_block_typeのパラメータで指定しないと
サーバーサイドでエラーになってしまうこと

考えてみりゃ当たり前ですが、考えずにやってるとつまづきます、つまづきました。

ということでregister_block_typeでrender_callbackとattributesは大体セットで指定することになります。

こんな感じに

PHP
register_block_type('myPlugin/myBlock',[
	'render_callback'=>function($attr){
		return sprintf('<p class="%s">MyBlock</p>',$attr['className']);
	},
	'attributes'=>[
		'className'=>['default'=>'myclass']
	]
]);

2023/04/05追記
WordPress6.2からServerSideRenderの読み込み方が変わりました。

JSX

const {ServerSideRender} = wp.components; //6.1以前

const {serverSideRender:ServerSideRender} = wp; //6.2以降

InspectorControls と PanelBody

ブロックを選択した時に表示されるサイドバーのコンポーネント。
PanelBodyでtitleを指定すると折りたたみにできます。
サイドバーはまず基本この二つを使って作ることになるだろうと思います。

JSX

const {InspectorControls} = wp.editor;
const {PanelBody} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<InspectorControls>
				<PanelBody title="パネルのタイトル">
				//ここにパネルの中身を書く
				</PanelBody>
			</InspectorControls>
		];
	}
);

PanelBodyは本来はPanelに入れてPanelHeaderと共に使うものっぽいんですが
正直Panelコンポーネントは見にくい使いにくいです、PanelBodyだけでいいです。

InspectorControlsってかなり使いそうなものなのに、公式ハンドブックにはBlock Controls: Toolbars and Inspectorのページで「InspectorControlsはHTMLモードでも表示されるからテキスト編集とかのは入れちゃダメだよ」という注意書きにしか登場してなくて、使い方とか全然書かれてません。

この情報が書かれていないハンドブックは不親切だと思います(切実)

BaseControl

サイドバーの入力項目の入れ物になるコンポーネント。
オリジナルのコンポーネントに、基本コンポーネントと同様にラベルやヘルプをつけられます。

JSX

const {InspectorControls} = wp.editor;
const {PanelBody, BaseControl} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<InspectorControls>
				<PanelBody title="パネルのタイトル">
					<BaseControl label="入力項目名" help="ヘルプ">
						入力項目
					</BaseControl>
				</PanelBody>
			</InspectorControls>
		];
	}
);

InnerBlocks

ブロックを入れ子にするためのコンポーネントです。
このコンポーネントは特に特別なブロックで、他のブロックとは処理されるフェーズが異なり、独特な制約が伴います。

JSX

const {InnerBlocks} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		return [
			<InnerBlocks template={[['core/paragraph'],['core/image']]}/>,
		];
	},
	save({attributes,className,setAttributes}){
		return <InnerBlocks.Content/>
	}
);

allowedBlocksで入れ子にできるブロックを制限しつつ自由に組み合わせ
templateで指定した固定の構造で組み合わせ

値やID与えるようになっていないため
一つのブロックにInnerBlocksは一つしか置けないです

また、saveはinnerBlocksを含む場合戻り値を配列にすることができません
saveは単一のコンポーネントを返す必要があります

この情報が書かれていないハンドブックは不親切だと思います(切実)

詳しい情報はGitHub

また、innerBlocksを含むブロック、例えばcore/columnsなどは
registerBlockStyleするとクラッシュするという問題があります
これはサイドバーでスタイル適用のプレビューをするタイミングでは
必要なデータがinnerBlocksの場合は揃っていないのが原因
なので上記の回答の中にもあるように、innerBlocksを含むブロックタイプの場合は
中身が空のコンポーネントを返すようにしてクラッシュを回避するなどします

そのうち修正されるとは思いますが5.1.1ではまだ修正されてません

// core/columnsでregisterBlockStyleがエラーを起こすバグの回避
wp.hooks.addFilter(
	'editor.BlockEdit',
	'my/editor',
	wp.compose.createHigherOrderComponent(function(BlockEdit){
		return function(props){
			var content=wp.element.createElement(BlockEdit,props);

			if(props.name==='core/columns' && typeof props.insertBlocksAfter==='undefined'){
				return <Fragment><div></div></Fragment>
			}

			return <Fragment>{content}</Fragment>;
		};
	},'allowColumnStyle')
);

Fragment

Reactでお馴染みの何も出力しないコンポーネント。
複数のコンポーネントをまとめて一つのコンポーネントとして扱いたいとかに使います。

また、Gutenbergはsaveの返すコンポーネントのclassName
wp-block-ブロック名のクラスを自動的に補完する様になっているのですが
ブロックのクラスをattributesの方でコントロールしたい場合にこれが邪魔になります。

saveで返すコンポーネントを<Fragment>でラップすることで
このクラス補完の処理を回避することができます。

registerBlockType('myPlugin/myBlock',{
	save({attributes}){
		return (
			<Fragment>
				<MyComponent className={attributes.classes}/>
			</Fragment>
		);
	}
);

Block API version 2からwp-block-ブロック名のクラスなど
Gutenbergが自動で付与していたプロパティは
useBlockPropsを使って明示的に付与しなければ付与されることはなくなりました

BlockControls と Toolbar

ブロックを選択した時に左上に出てくるツールバーを拡張するために使うコンポーネント。

const {BlockControls} = wp.blockEditor;
const {Toolbar} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		const {EditMode=false}=attributes;
		return (
			<BlockControls>
				<Toolbar
					controls={[
						{
							icon:'edit',
							title:'編集モード',
							isActive:EditMode,
							onClick:() => setAttributes({EditMode:!EditMode})
						}
					]}
				/>
			</BlockControls>
		);
	}
);

BlockAlignmentToolbar

BlockControlsに入れて使うブロックのレイアウトを選択するツールバーです。
値はleft,center,rightで固定です。

const {BlockControls} = wp.blockEditor;
const {Toolbar} = wp.components;

registerBlockType('myPlugin/myBlock',{
	edit({attributes,className,setAttributes}){
		const {blockAlignment='left'}=attributes;
		return (
			<BlockControls>
				<BlockAlignmentToolbar
					value={blockAlignment}
					controls={['left','center','right']}
					onChange={(blockAlignment)=>{setAttributes({blockAlignment})} }
				/>
			</BlockControls>
		);
	}
);

PluginSidebar と PluginSidebarMoreMenuItem

記事編集時に右側に出てくるサイドバーを拡張するためのコンポーネント。
wp.blocks.registerBlockTypeではなくwp.plugins.registerPluginで使います。

PluginSidebarが本体、PluginSidebarMoreMenuItemでサイドバーの表示項目の設定に追加しないと表示する術がなくなってしまうので、PluginSidebarPluginSidebarMoreMenuItemはいつもセットで使うことになるかと思います。

const {registerPlugin}=wp.plugins;
const {PluginSidebarMoreMenuItem,PluginSidebar}=wp.editPost;

const MySidebarPanelComponent = (props) => {
    return [
		<PluginSidebarMoreMenuItem target="MySidebarPanel">MySidebarPanel</PluginSidebarMoreMenuItem>,
        <PluginSidebar
            name="MySidebarPanel"
            title="MySidebarPanel"
            icon={edit}
        >
			<PanelBody title="MySidebarPanel" initialOpen={false}>
				MySidebarPanel
			</PanelBody>
        </PluginSidebar>
    ];
};
registerPlugin('MySidebarPanelComponent', { render: MySidebarPanelComponent } );

33
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?