0

Hey Guys I want to change my const TEMPLATE = [template] dynamically with the <InnerBlocks template={TEMPLATE} /> component. Based on a toggle I want to remove my 'core/image' block. I tried to create this with state and I set the state of my template and columns when I toggle them. Gutenberg gives a blocktype 'r' not recognized error.

My index.js file of the block can be found in here

const { __ } = wp.i18n;
import './styles/editor.scss'
import './styles/style.scss'
import edit from './edit';
import save from './save';

/**
 * Register block
 */

export const name = 'toolbox/three-cta';

export const settings = {
    title: __("Three CTA Block"),
    description: __("Display CTA block"),
    category: "widget",
    icon: "awards",
    attributes: {
        paragraph: {
            type: 'string',
            default: '',
            source: 'html',
            selector: 'p'
        },
        heading: {
            type: 'string',
            source: 'html',
            selector: 'h2'
        },
        cards: {
            type: 'number',
            default: 0,
        },
        toggleImg: {
            type: 'boolean',
            default: false,
        }
    },
    edit,
    save,
}

And in edit.js these attributes gets changed. I think it has something to do with the core blocks I might be setting. But I didnt change the names of these core blocks, so I dont understand why Gutenberg doesnt recognize it.

import { InnerBlocks, InspectorControls } from "@wordpress/block-editor";
import { __ } from "@wordpress/i18n";
import { PanelBody, PanelRow, RangeControl, ToggleControl } from "@wordpress/components";
import { useDispatch, useSelect } from "@wordpress/data";
import { createBlock } from "@wordpress/blocks";
import { useState } from "@wordpress/element";
const { times } = lodash;


// const TEMPLATE = [
// The template that should be reproduced. Based on the toggle  [ "core/image", {} ], should be removed
//  [ 'core/heading', { placeholder: 'Three CTA Block' } ],
//  [ 'core/columns', {}, [
//      [ 'core/column', {}, [
//          [ "core/image", {} ],
//          [ "core/heading", { placeholder: __( "Toolbox CTA" ) } ],
//          [ "core/paragraph", { placeholder: "CTA Description" } ],
//          [ "core/button", { placeholder: "Call to Action" } ],
//      ]
//      ],
//      [ 'core/column', {}, [
//          [ "core/image", {} ],
//          [ "core/heading", { placeholder: __( "Toolbox CTA" ) } ],
//          [ "core/paragraph", { placeholder: "CTA Description" } ],
//          [ "core/button", { placeholder: "Call to Action" } ],
//      ]
//      ],
//      [ 'core/column', {}, [
//          [ "core/image", {} ],
//          [ "core/heading", { placeholder: __( "Toolbox CTA" ) } ],
//          [ "core/paragraph", { placeholder: "CTA Description" } ],
//          [ "core/button", { placeholder: "Call to Action" } ]
//      ]
//      ],
//  ]
//  ] ];

export default function edit( props ) {
    const { className, attributes, setAttributes, clientId } = props;

    // code for the rangeControl Innerblocks doesnt affect the code (if not clicked on the rangeControls)
    const { replaceInnerBlocks } = useDispatch( "core/block-editor" );
    let { inner_blocks } = useSelect( select => ( {
        inner_blocks: select( "core/block-editor" ).getBlocks( clientId )
    } ) );

    let [column, setColumn] = useState([ 'core/column', {}, [
        [ "core/heading", { placeholder: __( "PLACEHOLDER" ) } ],
        [ "core/paragraph", { placeholder: "CTA P" } ],
        [ "core/button", { placeholder: "CTA Button" } ],
    ]])


    const [template, setTemplate] = useState([
        ["core/heading", { placeholder: "Three CTA Block" }],
        ["core/columns", {}, [...column]],
    ])



    const toggleChange = (value) => {
        setAttributes({ toggleImg: value })
        // const newColumn = column += ['core/column', {}, [["core/image", {}],]];
        const newColumn = [ 'core/column', {}, [
            [ "core/image", {} ],
            [ "core/heading", { placeholder: __( "Toolbox CTA" ) } ],
            [ "core/paragraph", { placeholder: "CTA Description" } ],
            [ "core/button", { placeholder: "Call to Action" } ],
        ]]

        setColumn(newColumn);
        setTemplate([
            ["core/heading", { placeholder: "Three CTA Block" }],
            ["core/columns", {}, [...newColumn]],
        ])

    }

    const getInspector = () => {
        return (
                <InspectorControls>
                    <PanelBody
                            title="Add columns"
                            initalOpen={true}
                    >
                        <PanelRow>
                            <RangeControl
                                    label="columns"
                                    value={attributes.cards}
                                    min={0}
                                    max={3}
                                    onChange={count => {
                                        let new_innerblocks = inner_blocks
                                        if ( attributes.cards < count ) {
                                            new_innerblocks = [
                                                ...inner_blocks,
                                                ...times( count - attributes.cards, () =>
                                                        createBlock( "toolbox/three-cta" )
                                                )
                                            ];
                                        } else if ( attributes.cards > count ) {
                                            inner_blocks = inner_blocks.slice( 0, count )
                                        }
                                        replaceInnerBlocks( clientId, new_innerblocks, false );
                                    }}
                            />
                        </PanelRow>
                        <PanelRow>
                            <ToggleControl
                                    label="Toggle me"
                                    checked={attributes.toggleImg}
                                    onChange={(value) => toggleChange(value)}
                            />
                        </PanelRow>
                    </PanelBody>
                </InspectorControls>
        )
    }

    return (
            <>
                {getInspector()}
                <div className={className}>
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/foundation.min.css" integrity="sha256-ogmFxjqiTMnZhxCqVmcqTvjfe1Y/ec4WaRj/aQPvn+I=" crossOrigin="anonymous"/>
                    <div className="grid-x">
                        <div className="cell small-12">
                            <InnerBlocks template={template} templateLock="true"/>
                        </div>
                    </div>
                </div>
            </>
    );
}

1 Answer 1

0

Neat implementation :)

The issue responsible for that error is here:

    const [template, setTemplate] = useState([
        ["core/heading", { placeholder: "Three CTA Block" }],
        ["core/columns", {}, [...column]],
    ])

As well as here:

        setTemplate([
            ["core/heading", { placeholder: "Three CTA Block" }],
            ["core/columns", {}, [...newColumn]],
        ])

If present, the third element of a block template block item array is supposed to be an array of inner block item arrays, but in both cases above you're spreading the contents of a single block item into the inner blocks container.

The block name "r" in the error message is a product of the block template API attempting to treat the characters in the string "core/column" as a block item array:

Block template API attempting to process a misplaced string

I think the proper solution is to just remove the array spread operator in both cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.