programing

InnerBlocks 속성을 가져와 상위 블록에 저장

codeshow 2023. 10. 14. 10:44
반응형

InnerBlocks 속성을 가져와 상위 블록에 저장

기본적으로 "Panel" 블록만 허용하는 InnerBlocks 구성요소인 "Tabbed Panels"(탭된 내용) 블록을 만들었습니다.패널을 작성할 때 패널에 제목을 지정해야 하며 이 제목은 패널 및 탭 버튼에서 사용됩니다.그래서 Tabbed Panels에 대한 렌더링 기능에서 하위 Panel 블록에서 제목을 끌어와야 합니다.

tabbed-panels-render.php 함수에서 regex를 사용하여 children html에서 적절한 속성을 검색하는 것과 같이 제가 사용할 수 있는 몇 가지 접근 방식이 있지만, 이것은 최선의 접근 방식이 아닌 것 같습니다.

가장 간단한 해결책은 패널 블록의 변경사항을 청취하고 변경사항(이 경우 머리글과 id)을 부모에게 저장하는 것입니다.저의 현재 접근 방식은 변화를 듣기 위해 후크를 사용하는 이 논의를 기반으로 합니다.그 부분은 잘 작동하는 것 같은데 출력물을 어딘가에 저장해야 해서 Tabbed Panels 블록 속성으로 저장하고 있습니다.이것은 처음에는 잘 작동하는 것처럼 보이지만, 편집 기능에 "setAttribute" 메서드를 직접 넣으면 문제가 발생합니다.페이지에 탭 패널 블록이 너무 많으면 반응이 "너무 많은 렌더링" 오류를 발생시킵니다.

내 "속성 설정" 기능은 어디에 있어야 하나요, 아니면 데이터를 자식에서 부모로 전달하는 더 나은 접근 방식이 있습니까?아이에게 useDispatch hook을 사용할까 생각했는데 이벤트를 많이 확인해야 합니다(제목 변경, 블록 순서 변경, 블록 삭제 등).

여기 관련 js와 php 파일이 있습니다.사용자 지정 요소가 몇 가지 있지만 구문 분석할 수 있어야 합니다.

tabbed- panels.js

import { arraysMatch } from 'Components/utils.js'
const { InnerBlocks } = wp.blockEditor
const { createBlock } = wp.blocks
const { Button } = wp.components
const { useDispatch, useSelect } = wp.data
const { __ } = wp.i18n

export const tabbedPanels = {
  name: 'my/tabbed-panels',
  args: {
    title: __('Tabbed Panels', '_ws'),
    description: __('Tabbable panels of content.', '_ws'),
    icon: 'table-row-after',
    category: 'common',
    supports: {
      anchor: true
    },
    attributes: {
      headings: {
        type: 'array',
        default: []
      },
      uids: {
        type: 'array',
        default: []
      }
    },
    edit: props => {
      const { setAttributes } = props
      const { headings, uids } = props.attributes
      const { insertBlock } = useDispatch('core/block-editor')
      const { panelHeadings, panelUids, blockCount } = useSelect(select => {
        const blocks = select('core/block-editor').getBlocks(props.clientId)
        return {
          panelHeadings: blocks.map(b => b.attributes.heading),
          panelUids: blocks.map(b => b.clientId),
          blockCount: select('core/block-editor').getBlockOrder(props.clientId).length
        }
      })
      if (!arraysMatch(panelHeadings, headings)) {
        setAttributes({ headings: panelHeadings })
      }
      if (!arraysMatch(panelUids, uids)) {
        setAttributes({ uids: panelUids })
      }
      return (
        <div className="block-row">
          <InnerBlocks
            allowedBlocks={ ['my/panel'] }
            templateLock={ false }
            renderAppender={ () => (
              <Button
                isSecondary
                onClick={ e => {
                  insertBlock(createBlock('my/panel'), blockCount, props.clientId)
                } }
              >
                { __('Add Panel', '_ws') }
              </Button>
            ) }
          />
        </div>
      )
    },
    save: props => {
      return (
        <InnerBlocks.Content />
      )
    }
  }
}

탭 panels render

<?php
function block_tabbed_panels($atts, $content) {
  $atts['className'] = 'wp-block-ws-tabbed-panels ' . ($atts['className'] ?? '');
  $headings = $atts['headings'] ?? '';
  $uids = $atts['uids'] ?? '';
  ob_start(); ?>
    <div class="tabs" role="tablist">
      <?php
      foreach ($headings as $i=>$heading) : ?>
        <button
          id="tab-<?= $uids[$i]; ?>"
          class="tab"
          role="tab"
          aria-selected="false"
          aria-controls="panel-<?= $uids[$i]; ?>"
          tabindex="-1"
        >
          <?= $heading; ?>
        </button>
        <?php
      endforeach; ?>
    </div>
    <div class="panels">
      <?= $content; ?>
    </div>
  <?php
  return ob_get_clean();
}

패널.js

import ComponentHooks from 'Components/component-hooks.js'
const { InnerBlocks, RichText } = wp.blockEditor
const { __ } = wp.i18n

export const panel = {
  name: 'my/panel',
  args: {
    title: __('Panel', '_ws'),
    description: __('Panel with associated tab.', '_ws'),
    icon: 'format-aside',
    category: 'common',
    supports: {
      customClassName: false,
      html: false,
      inserter: false,
      reusable: false
    },
    attributes: {
      heading: {
        type: 'string'
      },
      uid: {
        type: 'string'
      }
    },
    edit: props => {
      const { setAttributes } = props
      const { heading } = props.attributes
      return (
        <>
          <ComponentHooks
            componentDidMount={ () => setAttributes({ uid: props.clientId }) }
          />
          <RichText
            label={ __('Tab Name', '_ws') }
            placeholder={ __('Tab Name', '_ws') }
            tagName="h4"
            onChange={ newValue => setAttributes({ heading: newValue }) }
            value={ heading }
          />
          <InnerBlocks
            templateLock={ false }
          />
        </>
      )
    },
    save: props => {
      return (
        <InnerBlocks.Content />
      )
    }
  }
}

판넬 render

<?php
function block_panel($atts, $content) {
  $uid = $atts['uid'] ?? '';
  ob_start(); ?>
    <div
      id="panel-<?= $uid ?>"
      class="panel"
      role="tabpanel"
      aria-labelledby="tab-<?= $uid; ?>"
      tabindex="0"
      hidden="hidden"
    >
      <?= $content; ?>
    </div>
  <?php
  return ob_get_clean();
}

부모로부터 자식 블록에 액세스하여 속성(경우에는 탭 제목)을 가져올 수 있습니다.

componentDidUpdate(previousProps, previousState) {
    var myID = this.props.clientId;
    var tabs_title = [];
    this.myBlock = wp.data.select('core/block-editor').getBlock(myID);
    this.myBlock.innerBlocks.map(block => {
         tabs_title.push( block.attributes.title );
    });
    this.props.setAttributes({ 'tabs_title': tabs_title });
}

언급URL : https://stackoverflow.com/questions/59884842/getting-attributes-of-innerblocks-and-saving-them-to-parent

반응형