WPのブロックエディタで親の値を子に設定する:メモ

ブロックエディタ(Gutenberg)にはInnerBlocksで親子関係が作れますが、この状態で親の値を子に渡すためのメモです。

実現したいこと

  • ブロックエディタでInnerBlocksを用いるブロックを作成し、親となるブロックの値をInnerBlocksに渡す

例としては、親で設定したリンク先のアドレスを、子のaタグ(画像とボタンなど)にも渡すことで一度に指定するなどが考えられます。

実現方法

上記で回答されてるコードが該当し、親となるブロックのedit.jsの方に以下を参考にして記述します(一部省略しています)。


edit({ attributes, className, setAttributes, clientId }) {
  const { headerStyle } = attributes;

  const updateHeaderStyle = function( value ) {
    setAttributes({ headerStyle: value });

    // Update the child block's attributes
    var children = select('core/block-editor').getBlocksByClientId(clientId)[0].innerBlocks;
    children.forEach(function(child){
      dispatch('core/block-editor').updateBlockAttributes(child.clientId, {inheritedHeaderStyle: value})
    });
  }

  return (
    <>
      <InspectorControls>
        <PanelBody>
          <RadioControl
            label="Section Header Style"
            selected = {headerStyle}
            options = { [
              { label: 'h2', value: 'h2' }
            ]}
            onChange= {updateHeaderStyle}
          />
          </PanelBody>
        </InspectorControls>
      <InnerBlocks
        ...
      />
    <>
  );
}

続いて、親の値を用いたい子となるブロックのedit.jsに以下を記述します。


if (!inheritedHeaderStyle) {
  var parent = select('core/block-editor').getBlockParents(clientId);
  const parentAtts = select('core/block-editor').getBlockAttributes(parent);
  setAttributes( { inheritedHeaderStyle: parentAtts.headerStyle } )
}

しかしながら上記のサンプルのままではエラーが出たのと、ネストが深くなった場合に意図した動作にならなかったため、以下のように改造して用いました。


// 親ブロックのclientIdを配列で取得
var parentIds = select( 'core/block-editor' ).getBlockParents( clientId );
// 親ブロックの値を取得
 for( var parentId of parentIds ){
  let parentAtts = select( 'core/block-editor' ).getBlockAttributes( parentId );
  // 親ブロックのattributesに目的のキーがあれば実行
  if( parentAtts.headerStylef ){
    // 親の値をセット
    setAttributes( { inheritedHeaderStyle: parentAtts.headerStyle } );
    break;
  }
}

補足

  • 親の方では、子に渡すコードだけではなく、親用のatrributesに値を設定する
  • 子の方では、子用のatrributesに親のatrributesの値を渡す
  • 当然ながら、親も子もそれぞれatrributesを設定しておく
  • リロードのたびに更新ボタンが押せる状態になってしまう場合、block.jsで設定した該当のattributes"type":"text"だけにしてコメント内に保存する形にすると正常な状態になるかもしれない
  • 状況によっては、親の方のdispatchがなくとも動作する

上記末尾の件は実際に試した際に起こったことですが、明確な理由を突き止められていないものの推測としては以下を考えています。根拠はかなり薄いです。

  • 親の方でdispatchを使って子の情報を更新せずとも、子の方で何らかの操作をして情報を更新している際に親の値を取得している

参考資料

調査過程で調べた内容をメモとして。

選択中のブロックのattributesを取得/確認する


wp.data.select( 'core/block-editor' ).getSelectedBlock().attributes;

選択しているブロックのattributesを取得するコード。
投稿画面でブロックを選択状態にした上で、このコードをそのまま開発者ツールのコンソールに書くと、該当のブロックに設定されたattributesが表示されるためとても便利でした。

親のブロックの情報を取得する

基本的には以下の流れになります。

  1. getBlockParentsで親のClientIDを取得
  2. 取得したClientIDgetBlockAttributesに入れる
  3. 親のattributesを取得する

ネストは深くできるため、getBlockParentsで取得できる親のClientIDは配列になっています。
並び順は変更可能で、第二引数にtureを指定して切り替え可能です(初期値はfalse)。


//下層から上層へ → bottom to top (true)
select( 'core/block-editor' ).getBlockParents( clientId, ture );

//上層から下層へ → top to bottom (false)
//第二引数を記載しない場合の初期値
select( 'core/block-editor' ).getBlockParents( clientId, false );

その他

結び

動作は確認していますが、内部で理解できない動きをしている部分もあり、少々不安が残ります。

0人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄