【WordPress】自作カスタムブロックでのdata属性の編集方法

ブロックテーマの構築方法とReactの勉強をぼちぼち進めているこの頃です。(React初心者)
このブログのエディタの置換をローカルで行っていたところ、<p data-▲▲▲=”●●●”></p>などのdata属性をエディタの編集対象にする方法が分からずつまずいてしまいました。

この記事では、覚書として自作カスタムブロックにおけるdata属性の編集方法をまとめています。

プラグインは利用しない(React使用の)カスタムブロックの構築方法になります。

要素の属性を編集対象にしたい時の書き方

まず、そもそもHTMLコードの属性をWP編集画面上の編集対象にしたい場合はどうするか?について。
こちらは公式ハンドブックに書いてありました。

Attributes | Block Editor Handbook | WordPress Developer Resources

サンプルとして、画像のURLを入力すると画像が出力されるカスタムブロックを作ってみました。
ここではURLの入力欄にTextControlを使います。

完成イメージ

◆ WEBページでの表示

◆ WEBページへの出力ソースコード

<img decoding="async" src="https://blog.webico.work/wp-content/uploads/2023/04/26321233_m.jpg.webp">

decoding=”async”はWP6.1から自動で付与されてるようなので、構築時はスルー

◆ エディタ上でカスタムブロックの見栄え


画像のURLを入力するとimgタグで出力

構築内容

画像URLの変数は「url」として記述していきます。

◆ block.json

  • “className”: false
  • “attributes”を以下の通り追加
"attributes": {
	"url": {
		"type": "string",
		"source": "attribute",
		"selector": "img",
		"attribute": "src"
	}
},

◆ edit.js

  • TextControlをインポート
  • Edit関数を下記の通り修正
(省略)
export default function Edit({ attributes, setAttributes }) {
	const blockProps = useBlockProps({
		tagName: "img",
		value: attributes.url,
		label: "画像のURL",
		placeholder: "ここにURLを入力・・・",
		onChange: (newURL) => {
			setAttributes({ url: newURL });
		}
	});
	return (
		<TextControl {...blockProps} />
	);
}

◆ save.js

  • save関数を下記の通り修正
(省略)
export default function save({ attributes }) {
	return (
		<img src={ attributes.url } />
	);
}

以上で、画像のURLを入力するカスタムブロックが作成できました!
block.jsonの変数定義の際に、“source”: “attribute”“attribute”: “属性名”を指定してあげることがポイントです。

data属性を編集対象にしたい時の書き方

本題のdata属性ですが、こちらも基本的には同様の方法で可能です。

私がつまづいた問題に関しては後述しますが、まずはサンプルとしてラベルのテキスト(data属性)と文章(pタグ)を入力できるカスタムブロックを作成していきます。
data属性部分は先と同じようにTextControl、テキスト入力部分にRichTextを使ってみます。

完成イメージ

◆ WEBページでの表示

◆ WEBページへの出力ソースコード

<p class="mark" data-label="POINT">おすすめです!</p>

◆ エディタ上でカスタムブロックの見栄え


上のTextControlを入力するとラベル内(data-label)のテキストが変更、またラベル右のRichTextの入力欄からpタグ内の編集が可能

構築内容

変数はラベルを「label」、リッチテキストを「text」として記述していきます。

◆ block.json

  • “className”: false
  • “attributes”を以下の通り追加
"attributes": {
	"text": {
		"type": "string",
		"source": "html",
		"selector": "p.mark"
	},
	"label": {
		"type": "string",
		"source": "attribute",
		"selector": "p.mark",
		"attribute": "data-label"
	}
},

◆ edit.js

  • RichTextとTextControlをインポート
  • Edit関数を下記の通り修正
export default function Edit({ attributes, setAttributes }) {
	const blockProps = useBlockProps({
		tagName: "p",
		className: "mark",
		value: attributes.text,
		"data-label": attributes.label,
		onChange: (newTEXT) => {
			setAttributes({ text: newTEXT });
		}
	});
	return (
		<>
			<TextControl
				label = "ラベル"
				value = { attributes.label }
				onChange = { ( newLABEL ) => {
					setAttributes({ label: newLABEL });
				} }
			/>
			<RichText {...blockProps} />
		</>
	);
}

◆ save.js

  • RichTextをインポート
  • save関数を下記の通り修正
export default function save({ attributes }) {
	const blockProps = useBlockProps.save({
		tagName: "p",
		className: "mark",
		value: attributes.text,
		"data-label": attributes.label
	});
	return (
		<RichText.Content {...blockProps} />
	);
}

◆ style.scss

  • edit.scssとstyle.scssの既存スタイルを削除
  • style.scssに以下の通り追加
.mark::before{
	content: attr(data-label);

	padding: 0.5em 1em;
	background-color: #00c0e5;
	color: #fff;
	border: solid 1px #fff;
	outline: solid 2px #00c0e5;
	font-size: 95%;
	margin-right: 1em;
}

以上でラベルのテキストと文章を編集できるカスタムブロックが完成!
エディタ上で以下のように編集すると、ラベル、テキスト共に反映されていることが確認できます。


エディタ編集画面


WEBページ表示

data属性を編集対象にしたい時の注意点

私が遭遇した問題の結論として、「edit.jsでuseBlockProps()を呼びだす要素においてはdata-title・data-block・data-typeは使わず、その他のdata属性を使った方がよさそう」ということです。

どういうことかというと、問題につまづいた経緯・概要がこちら。

  • 最初data-titleを使って以下のようなマークアップにしていた
    <p class="mark" data-title="POINT">おすすめです!</p>
  • 前述した通りカスタムブロックを構築したところ、エディタ画面で下記のような見た目になってしまった

    *上のTextControl入力欄を変更しても、ラベルボックス内のテキストが変わらない(Test Label固定)
  • しかしWEBページ上ではTextControl入力欄に入力した通りの内容が反映されている(つまり、エディタ画面だけ表示がおかしくなる)

これはなぜかと思い調べたところ、以下のことがわかりました。

  • edit.jsで記述しているuseBlockProps()の戻り値にはdata-block、data-type、data-titleが含まれている
  • useBlockProps()は今回p.mark要素で呼び出しており、エディタ上ではp.mark要素に最初から3つのdata属性が記述されている状態

(省略)
‘data-block’: clientId,
‘data-type’: name,
‘data-title’: blockTitle,
(省略)

useBlockProps()の戻り値

<p role="document" aria-multiline="true" aria-label="ブロック: Test Label" tabindex="0" class="●●● mark is-selected wp-block-create-block-test-label rich-text" id="block-●●●" data-block="●●●" data-type="create-block/test-label" data-title="Test Label" contenteditable="true" style="white-space: pre-wrap; min-width: 1px;">おすすめです!</p>
  • data-block、data-type、data-titleが初期から入ってることが確認できる
  • data-titleはブロックのタイトルが出力されるので、今回はブロック名「Test Label」が表示

おそらくそれらを上書きできないため、data-title属性の変更が効かなかったということだと予想。

エディタにおいてdata-*属性は全て使用が許可されているように見えるので(以下引用参照)、edit.jsにおけるuseBlockProps()呼び出し要素だけこの3つのdata属性を使わないよう気をつけておくといいのかなと考えています。

(省略)
/* Helper function to add global attributes to a tag in the allowed HTML list. */
(省略)
‘aria-describedby’ => true,
‘aria-details’ => true,
‘aria-label’ => true,
‘aria-labelledby’ => true,
‘aria-hidden’ => true,
‘class’ => true,
‘data-*’ => true,
‘dir’ => true,
‘id’ => true,
‘lang’ => true,
‘style’ => true,
‘title’ => true,
‘role’ => true,
‘xml:lang’ => true,
(省略)

WordPress/wordpress-develop · GitHub

おわりに

同じ疑問がなかなか見つからなかったので覚書きでした。
エラーの「Block validation: Block validation failed for…」がもう少し詳細のわかるメッセージだとありがたいなぁと思いつつ、Reactの勉強も精進します。

サンプルコードはログに残したいポイントだけわかるように書いた最低限のものです。
こちらの方が実用的な書き方かなと思うのを下記記事にまとめました。よかったらどうぞ!