GutenbergのRitchTextを使った時に上手く保存できずハマったので、注意点をまとめました。RitchTextの基本的な使い方はBlock Editor Handbookに書いてあります。
基本的なコード
RichTextを使う場合のベーシックなコードは次のようになります。h2
タグで囲まれた見出しが出力されます。Block Editor Handbookの例をアレンジました。
const { registerBlockType } = wp.blocks;
const { RichText } = wp.blockEditor;
registerBlockType( /* ... */, {
// ...
attributes: {
title: {
type: 'string', // データ型
source: 'html', //どのようにデータを取り出すか
selector: 'h2', //対象要素
}
}
edit(props){
const {
attributes: {
title,
},
} = props;
<RichText
tagName="h2" //管理画面で囲むタグ、クラスやIDは設定できない
value={title} // 入力エリアに表示する値。ここではtitleに保存されている値を指定
onChange={newTitle => {
setAttributes({title: newTitle,}); //変更した場合にその値をtitleに設定する指示
}}
/>
},
save(props) {
const {
attributes: {
title,
},
} = props;
<RichText.Content
tagName="h2"
value={title}
/>
}
};
これで出力されるHTMLは次のようになります。
<h2>titleに入力したテキスト</h2>
attributesの指定が重要
attrivubtes
はブロックが保持するデータのことで、最初に定義しておく必要があります。
source
を指定しない場合、設定した値はブロックコメントの属性値として保持されます。この場合はtype
を適切なのものにするだけでよいです。チェックボックスやセレクトボックスの値を保存する場合に向いています。
source
を指定した場合は、ブロック内のどの要素(selector
)のどの部分(source
)を使うか適切に指定する必要があります。
先ほどの例ではブロック内のh2
タグの中身をhtml形式で取り出したものをtitle
の値として使うという意味になります。source
がtextの場合はテキスト(タグも変換されます)としてtitle
の値に使われます。
soruce
に指定できる形式は次のようなものがあります。
- children(child node:子ノード)
- html(内部の HTML)
- text(内部のテキスト)
- attribute(属性の値)
- query(値の配列)
- meta(投稿のメタ情報)
queryやmetaにつていは私もよく理解できていませんが、通常のテキスト編集であればhtmlかtextを知っておけばよいと思います。
selectorの指定は慎重に
今回、私がハマったポイントはselector
の指定でした。selector
は無指定だとブロックのルート要素が設定されます。ですので、うっかり無指定のままだとブロックの中身全体がごっそりtitle
の値に挿入されてしまいます。シンプルなブロックの場合はそれでもよいですが、複雑なブロックの場合は必ず指定する必要があります。
また、selector
にdiv
というようなブロック内でたくさん使われる要素を設定してしまうと、どのdiv
から値を持ってるくるか区別できず意図した結果になりません。
例えばタイトル付きのボックスブロックを作るとして、そのタイトルの部分にRichTextを使う場合を考えます。タイトルはdiv
要素で囲むので下記のように書きました。
attributes: {
title: {
type: 'string', // データ型
source: 'html', //どのようにデータを取り出すか
selector: 'div', //対象要素
}
}
edit(props) {
// ...
<div className="box_block">
<div className="box_title">
<RichText
value={title}
onChange={newTitle => {
setAttributes({title: newTitle,});
}}
placeholder={タイトルを入力}
</div>
<div className="box_content">
<InnerBlocks />
</div>
</div>
},
save(props) {
// ...
<div className="box_block">
<div className="box_title">
<RichText.Content value={title} />
</div>
<div className="box_content">
<InnerBlocks.Content />
</div>
</div>
}
これで保存すると、なんと.box_title
の中に.box_block
の中身が入った状態で保存されてしまいブロックエラーが出ます。
私としてはこの書き方で、RichTextを書いた部分の親のdiv(.box_title)を参照すると思っていたのですが、実はそうではなくブロックのルートから辿って最初のdiv
を参照する指定になっていました。
ハンドブックの例のようにh2
タグなら一つのブロックに1回ぐらいしかでてこないと思うので問題ないですが、div
をのように複数使う可能性があるタグを対象とする場合は注意が必要です。
解決策は簡単で、クラスまたはIDを指定して親要素を絞り込むことです。上の例場合は次の様にクラス名を付与すればOKです。
attributes: {
title: {
type: 'string',
source: 'html',
selector: '.box_title',
}
}
これで、無事にボックスのタイトルが保存されブロックエラーも出なくなります。attirbutes
の指定はよく考えておこないましょう。
RichTextの属性値
tagName
String型
RitchTextを囲むタグ。これを指定した要素で自動的にラップされるます。div
のように複数使われるタグだとseletor
の指定が上手くできず上に書いたような問題が出る可能性があります。そのため、上に書いたボックスのコードではRichTextにtagNameを指定せずラップ要素を直接書いています。
placeholder
String型
入力フィールドのプレースホルダーテキスト。ブロックエディタではプレースホルダーを表示しておかないとユーザーが入力フィールドを認識できない場合があるので基本的には設定しておいた方が良いと思います。
keepPlaceholderOnFocus
Boolean型
デフォルトでは入力フィールドを選択・フォーカスするとプレースホルダーテキストは消えますが、trueにするとフィールドに入力するまで消えません。日本語だと入力を開始しても確定するまでプレースホルダーが表示され続けるので微妙かも。
他にも属性値はいろいろありますが、タイトルの設定など簡単な場面でRitchTextを使う場合はこれぐらいまで知っておけば何とかなると思います。
他に属性の説明は
Gutenberg RichText コンポーネント和訳 – Qiita
を見るとわかりやすいと思うので参照してみてください。
コメント
この記事へのコメントはありません。