前回(WordPressのブロック開発メモ その2 TypeScript編)の続きです。
属性
これまでsave
及びedit
は単に固定されたメッセージを表示するだけの最低限のコードでした。
今度はedit
での編集を保存し、save
で表示出来るように改良します。
編集するデータを保存するには属性を使います。
例えばメッセージを編集するためにmessage
という属性を使うことにします。
インターフェースKurageExampleBlockProps
にmessage
を追加しますが、
その前にこのインターフェースをindex.ts
から分離しましょう。
save
とedit
両方から参照されるのでそのままだと気持ち悪いです。
これまで以下の用になってたindex.ts
からKurageExampleBlockProps
を分離します。
interface KurageExampleBlockProps
{
}
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
attributes: {},
title: metadata.title,
category: metadata.category,
edit: Edit,
save,
};
まずはインターフェース側。
適当にprops.ts
とでも名付けてファイルを分けます。
string
型のmessage
プロパティを追加します。
interface KurageExampleBlockProps
{
message: string;
}
元のindex.ts
側です。
// propsを読み込む
import KurageExampleBlockProps from './props';
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
attributes: {
message: {
type: 'string'
}
},
title: metadata.title,
category: metadata.category,
edit: Edit,
save,
};
属性にmessage
を追加します。
追加するにはattributes
プロパティのオブジェクトにmessage
を追加します。
さらにmessage
が何の型なのかをtype
を設定します。
今回は文字列型のstring
を指定。他にもarray
, boolean
, number
, integer
, object
, null
などのtype
があります。
edit.tsx
も変更。
面倒なのでロケール類は外します。
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
import React from 'react';
import { BlockEditProps } from '@wordpress/blocks';
import KurageExampleBlockProps from './props';
export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
const { message } = props.attributes;
const { setAttributes } = props;
return (
<p {...useBlockProps()}>
<p>{ message }</p>
<input
type="text"
value={message}
onChange={ e => setAttributes({ message: e.target.value }) }
/>
</p>
);
}
コンポーネントのprops
に型を定義します。
export default (props: BlockEditProps)
attributes
で設定したmessage
は、props.attributes.message
で取得出来ます。
さらにprops.setAttributes
を使い、属性の値を変更することも出来ます。
ようやくReact使ってるっぽくなってきました。
edit.save
の方も変更します。
import { useBlockProps } from '@wordpress/block-editor';
import { BlockSaveProps } from '@wordpress/blocks';
import React from 'react';
import KurageExampleBlockProps from './props';
export default (props: BlockSaveProps<KurageExampleBlockProps>) =>
{
return (
<p { ...useBlockProps.save() }>
{ props.attributes.message }
</p>
);
}
props
の型を定義します(edit
のpropsの時とは型が違うので注意)
export default (props: BlockSaveProps)
実際に実行結果を見ていきます。
edit
のページ(入力出来ます)
save
のページ(プレビューしてみます)
そして保存した時のDBの結果
コメントに隠れて
wp:ブロック名
属性のリテラルオブジェクト
こんな形で保存されていることが分かります。
編集を保存した時にHTML化されてDBに入ってるようですね。
ページ表示毎にsaveコンポーネントがレンダリングされているわけではないようです。
属性の保存先
何も指定しない場合コメントに含まれてました。
source
を指定すると保存先を変更出来ます。
ソースがattributeの時
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
attributes: {
message: {
type: 'string',
source: 'attribute',
selector: 'p',
attribute: 'data-atr'
}
},
title: metadata.title,
category: metadata.category,
edit: Edit,
save,
};
source
にattribute
を選びます。
selector
はそのままセレクタのことで今回はp
としています。
attribute
はPタグの属性名を指定します。
Reactで実在しない属性は怒られるのでdata-
を使うことにします。属性名にdata-atr
を指定しました。
これで
することになります。
そしてsave.tsx
のほうもそれに合わせます。
export default (props: BlockSaveProps<KurageExampleBlockProps>) =>
{
return (
<p { ...useBlockProps.save() } data-atr={ props.attributes.message }>
{ props.attributes.message }
</p>
);
}
data-atr
を追加します。
これでP
タグのdata-atr
属性にデータを保存することになります。
DBを見ると
確認出来ます。
source
がtext
の場合
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
attributes: {
message: {
type: 'string',
source: 'text'
}
},
title: metadata.title,
category: metadata.category,
edit: Edit,
save,
};
export default (props: BlockSaveProps<KurageExampleBlockProps>) =>
{
return (
<p { ...useBlockProps.save() }>
{ props.attributes.message }
</p>
);
}
単にテキストに保存します。
ここに保存される
他にも属性にhtml
がありますがこれはまた後日紹介します。
サポートのalignのデータはどこに?
一旦話を戻して、前回のalign
のサポートを思い出してください。
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
attributes: {
message: {
type: 'string'
}
},
supports: {
align: true,
alignWide: true,
},
example: {},
title: metadata.title,
category: metadata.category,
edit: Edit,
save,
};
align
属性が追加されていることが分かります。
useState()が使えるけど
useState()
も使えます。
そのままだとインテリセンスが使えないのと、どうせなら次の型定義を追加します。
npm install --save-dev @types/wordpress__element
ただuseState()のデータは保存してないので更新する毎にリセットされます。
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
import React from 'react';
import { BlockEditProps } from '@wordpress/blocks';
import { useState } from "@wordpress/element";
import KurageExampleBlockProps from './props';
export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
const { message } = props.attributes;
const { setAttributes } = props;
const [ firstName, setFirstName ] = useState('');
const [ lastName, setLastName ] = useState('');
const updateMessage = () =>
{
setAttributes({
message: `Hello ${firstName} ${lastName} !`
});
};
return (
<p {...useBlockProps()}>
<p>{ message }</p>
<input
type="text"
value={message}
onChange={ e => setAttributes({ message: e.target.value }) }
/>
<fieldset>
<input
type="text"
value={firstName}
onChange={ e => setFirstName(e.target.value) }
/>
<input
type="text"
value={lastName}
onChange={ e => setLastName(e.target.value) }
/>
<button onClick={ e => updateMessage() }>補助入力</button>
</fieldset>
</p>
);
}
補助としては使えるものの、
ページを更新すると、リセットされます。
保存してないので当然なのですが、例えばuseEffect(..., [lastName, firstName])
でsetAttributes()
を更新しようとすると、ブロックが更新されるたびにリセットされた状態で更新されてしまいます。
今のところ補助用として使ってます。
今回はReact標準のコンポーネントを使いました。
次回からはWordPress(Gutenberg)コアが提供しているコンポーネントを使っていきます。