admin管理员组

文章数量:1290374

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="/[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>
            </>
    );
}

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/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>
            </>
    );
}
Share Improve this question asked Jun 7, 2021 at 19:30 Mien SaoMien Sao 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 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:

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

本文标签: plugin developmentRerender core Templates with with ToggleControl but it doesnt recognize block type