5

I got everything working based on this: https://gist.github.com/pento/cf38fd73ce0f13fcf0f0ae7d6c4b685d its just that the toggle does not get the visual representation of being toggled on. Any tutorials on this? Everything I find is complicated "real" blocks stuff tons of imports and this react style returns and things I do not need at this point. I just want to know how to get the toggle to work.

PHP

<?php
function register_gb_block() {

    // ...

    register_assets();
    register(
        [
            'handle' => 'arve-block',
            'src'    => plugins_url( 'dist/js/test-block.js', PLUGIN_FILE ),
            'deps'   => [ 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' ],
            'ver'    => ver( VERSION, 'dist/js/test-block.js', PLUGIN_FILE ),
            'footer' => false
        ]
    );

    wp_localize_script( 'arve-block', 'ARVEsettings', $sc_settings );

    // Register our block, and explicitly define the attributes we accept.
    register_block_type(
        'nextgenthemes/arve-block',
        [
            'attributes'      => array(
                'foo' => array(
                    'type' => 'string',
                ),
                'toggle' => array(
                    'type' => 'boolean',
                ),
            ),
            'editor_script'   => 'arve-block',
            'editor_style'    => 'advanced-responsive-video-embedder',
            'render_callback' => __NAMESPACE__ . '\shortcode'
        ]
    );
}

The register is just a wrapper around wp_register_script

JS

// License: GPLv2+ based on: https://gist.github.com/pento/cf38fd73ce0f13fcf0f0ae7d6c4b685d

const el = wp.element.createElement,
    registerBlockType = wp.blocks.registerBlockType,
    ServerSideRender = wp.components.ServerSideRender,
    TextControl = wp.components.TextControl,
    ToggleControl = wp.components.ToggleControl,
    InspectorControls = wp.editor.InspectorControls;

/*
 * Here's where we register the block in JavaScript.
 *
 * It's not yet possible to register a block entirely without JavaScript, but
 * that is something I'd love to see happen. This is a barebones example
 * of registering the block, and giving the basic ability to edit the block
 * attributes. (In this case, there's only one attribute, 'foo'.)
 */
registerBlockType( 'nextgenthemes/arve-block', {
    title: 'PHP Block',
    icon: 'megaphone',
    category: 'widgets',

    /*
     * In most other blocks, you'd see an 'attributes' property being defined here.
     * We've defined attributes in the PHP, that information is automatically sent
     * to the block editor, so we don't need to redefine it here.
     */

    edit: ( props ) => {
        return [
            /*
             * The ServerSideRender element uses the REST API to automatically call
             * php_block_render() in your PHP code whenever it needs to get an updated
             * view of the block.
             */
            el( ServerSideRender, {
                block: 'nextgenthemes/arve-block',
                attributes: props.attributes,
            } ),
            /*
             * InspectorControls lets you add controls to the Block sidebar. In this case,
             * we're adding a TextControl, which lets us edit the 'foo' attribute (which
             * we defined in the PHP). The onChange property is a little bit of magic to tell
             * the block editor to update the value of our 'foo' property, and to re-render
             * the block.
             */
            el( InspectorControls, {},
                el(
                    TextControl,
                    {
                        label: 'Foo',
                        value: props.attributes.foo,
                        onChange: ( value ) => {
                            props.setAttributes( { foo: value } );
                        },
                    }
                ),
                el(
                    ToggleControl,
                    {
                        label: 'Toogle',
                        value: props.attributes.toggle,
                        onChange: ( value ) => {
                            props.setAttributes( { toggle: value } );
                        },
                    }
                ),
            ),
        ];
    },

    // We're going to be rendering in PHP, so save() can just return null.
    save: () => {
        return null;
    },
} );

1 Answer 1

4
+50

The issue is that in ToggleControl you are using the wrong prop for the value. It should be checked instead of value.

Also use the blockEditor package instead of editor for InspectorControls as it will be deprecated.


el(
    ToggleControl,
    {
        label: 'Toogle',
        checked: props.attributes.toggle, // here
        onChange: ( value ) => {
            props.setAttributes( { toggle: value } );
        },
    }
)

The reason why it updates the value correctly although it is not displaying it correctly is because the component ToggleControl is using a state which is outside of the component. This state, which is represented by attributes + setAttributes, is being correctly updated using setAttributes. However, it is not being correctly displayed as the prop checked is not showing the update value. This means that checked will use its default value which seems to be false.

4
  • value: props.attributes.toggle.checked, or what? checked: props.attributes.toggle, ??? Sep 8, 2019 at 9:12
  • @NextGenThemes my intention was to help, not really interested in the +50. I thought it was clear, but sure, I'll update the answer with the exact code. If there is anything else I can be of help just let me know.
    – Alvaro
    Sep 8, 2019 at 9:22
  • Ahh OK my 2nd guess was the right one. Thanks, keep in mind that even if it might be obvious to you a little code is always helpful to make it more clear. Especially when a bounty for "A detailed canonical answer is required to address all the concerns." is out ;) Still a bit confused as to why value actually also works but just the UI fails on it but I guess I learn about the deeps of Gutenberg another day. Sep 8, 2019 at 9:30
  • @NextGenThemes I expanded to explained why it is not working, check the update. If you accept an advice, dive into JSX syntax as soon as you can. At first it might be intimidating, specially all the setup with compilers (Babel) and bundlers (Parcel or Webpack), but then it makes reading and writing code much easier.
    – Alvaro
    Sep 8, 2019 at 9:35

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.