Пользовательский блок Gutenberg: добавление элементов по длине innerBlocks - PullRequest
0 голосов
/ 17 ноября 2018

Контекст : я работаю над плагином Custom Gutenberg. Один из блоков, который я пытаюсь создать, - это Карусель (с использованием Карусели Bootstrap).

Я пытаюсь по желанию добавить индикаторы, основанные на количестве дочерних блоков. Я получаю ошибку: Block validation: Block validation failed

Это определенно как-то связано с тем, что я добавил индикаторы. Вот мой блок. Кто-нибудь может помочь?

/**
 * BLOCK: Laboratory Blocks Carousel
 */
import classNames from 'classnames';
import { Fragment } from 'react';
import CarouselOptions, {
  CarouselOptionAttributes,
} from './options';
import heightClass from './classes';

const { registerBlockType } = wp.blocks;
const { InspectorControls, InnerBlocks } = wp.editor;
const { select, dispatch } = wp.data;
const { __ } = wp.i18n;
const ALLOWED_BLOCKS = [];

registerBlockType('laboratory-blocks/carousel', {
  title: __('LB Carousel'),
  icon: 'slides',
  category: 'laboratory-blocks',
  description: __('A Bootstrap Carousel'),
  supports: { anchor: true },
  keywords: [
    __('Carousel'),
    __('Slider'),
  ],
  attributes: {
    ...CarouselOptionAttributes,
    test: {
      type: 'object',
    },
    clientId: {
      type: 'string',
      default: 'laboratory-carousel',
    },
  },

  edit(props) {
    const { setAttributes, isSelected } = props;
    const { clientId } = props;
    // find innerBlocks, add "active" to the first slide, set attribute slideLength
    const children = select('core/editor').getBlocksByClientId(clientId)[0].innerBlocks;
    const firstChild = children[0] || false;
    if (firstChild) {
      dispatch('core/editor').updateBlockAttributes(firstChild.clientId, { className: 'active' });
      setAttributes({ clientId });
    }

    return [
      !!isSelected && (
        <InspectorControls key="inspector">
          <CarouselOptions {...props} />
        </InspectorControls>
      ),
      <Fragment>
        <p>Laboratory Blocks Carousel:&nbsp;
          <small>Include a unique ID under &quot;Carousel Options&quot;</small>
        </p>
        <hr />
        <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} />
      </Fragment>,
    ];
  },

  save(props) {
    const { className, attributes, innerBlocks } = props;
    const {
      carouselHeight,
      hasControls,
      hasIndicators,
      interval,
      pauseOnHover,
      carouselId,
    } = attributes;
    const height = heightClass(attributes);
    const classes = classNames(className, 'carousel', 'slide', height);
    const styles = carouselHeight ? { height: carouselHeight } : {};
    const timing = interval || false;
    const hover = pauseOnHover ? 'hover' : false;

    const containerTags = {
      ID: carouselId,
      className: classes,
      style: styles,
      'data-ride': 'carousel',
      'data-interval': timing,
      'data-pause': hover,
    };

    let Indicators;
    if (innerBlocks && 0 < innerBlocks.length) {
      Indicators = innerBlocks.map((block, i) => {
        const c = (0 === i) ? 'active' : '';
        return (
          <li
            key={`${carouselId}-trigger-${block.clientId}`}
            data-target={`#${carouselId}`}
            data-slide-to={i}
            className={c}
          />
        );
      });
    }

    return (
      <div {...containerTags}>
        <InnerBlocks.Content />
        {
          hasControls && (
            <Fragment>
              <a claclassName="carousel-control-prev" href={`#${carouselId}`} role="button" data-slide="prev">
                <span className="carousel-control-prev-icon" aria-hidden="true" />
                <span className="sr-only">Previous</span>
              </a>
              <a claclassName="carousel-control-prev" href={`#${carouselId}`} role="button" data-slide="next">
                <span className="carousel-control-next-icon" aria-hidden="true" />
                <span className="sr-only">Next</span>
              </a>
            </Fragment>
          )
        }
        {
          hasIndicators && (
            <ol className="carousel-indicators">
              {Indicators}
            </ol>
          )
        }
      </div>
    );
  },
});

1 Ответ

0 голосов
/ 14 декабря 2018

Мое решение:

  1. Переместите индикаторы (точки карусели) в отдельный компонент для повторного использования кода.
  2. Использовали его в обоихметоды редактирования и сохранения.
  3. Сохранение количества внутренних блоков в функции редактирования и установка его в качестве атрибута для использования в функции сохранения.

`` `

registerBlockType('laboratory-blocks/carousel', {...},
    edit: {
      const { clientId } = props;

      ...

      // find number of children and set it as an attribute
      const innerCount = select('core/editor').getBlocksByClientId(clientId)[0].innerBlocks.length;
      setAttributes({ clientId, innerCount });

      return [
        <div>
          ...
          <Indicators count={attributes.innerCount} clientId={clientId} />
        </div>
      ];
    }
    save: {
      const { clientId, attributes } = props;
      const { innerCount } = attributes;
      ...

      return [
        <div>
          ...
          <Indicators count={innerCount} clientId={clientId} />
        </div>
      ];
    }
}

`` `

...