maja
maja

Reputation: 175

Gutenberg server side rendered (dynamic) block - attributes don't update in editor

I'm making Wordpress server side rendered block and it works well on frontend, but in editor attributes don't save (I have always default value in editor, although on frontend there is my saved value).

This is my code (not whole but minimal reproducible).

Register block on client side and set block options in editor:

const { __ } = wp.i18n;
const { ServerSideRender } = wp.editor;
const { InspectorControls } = wp.blockEditor;
const { PanelBody, __experimentalNumberControl: NumberControl } = wp.components;

registerBlockType(
    'mysite/trainings',
    {
        title: __( 'Trainings list', 'mysite' ),
        attributes: {
            postsCount: {
                type: 'number',
                default: 9,
            }
        },

        edit: ( { attributes, setAttributes } ) => {
            const { postsCount } = attributes;

            return (
                <>
                    <InspectorControls>
                        <PanelBody
                            title={ __( 'Set number of displayed trainings', 'mysite' ) }
                        >
                            <NumberControl
                                value={ postsCount }
                                onChange={ ( value ) => setAttributes( { postsCount: value } ) }
                                min={ 1 }
                                max={ 9 }
                            />
                        </PanelBody>
                    </InspectorControls>
                    <ServerSideRender
                        block="mysite/trainings"
                        attributes={ {
                            postsCount: 9,
                        } }
                    />
                </>
            );
        },
        save() {
           return null;
        },
    }
);

Register and render block on server side:


add_action( 'init', 'register_trainings_block' );

function register_trainings_block() {

    register_block_type(
        'mysite/trainings',
        array(
            'api_version'     => 2,
            'editor_script'   => 'sm_editor_script',
            'render_callback' => 'render_trainings_block',
            'attributes'      => array(
                'postsCount' => array(
                    'type'    => 'number',
                    'default' => 9,
                ),
            ),
        )
    );
}

function render_trainings_block( $attributes ) {

    $query_args = array(
        'post__in' => array(
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10 // IDs of posts
        ),
        'post_type' => 'sm_training',
        'orderby' => 'post__in',
        'paged' => '1'
    );

    $posts = new WP_Query( $query_args );

    $output = '<section class="wp-block-mysite-trainings">';

    $i = 0;
    foreach ( $posts->posts as $post ) {

        if ( $i < $attributes['postsCount'] ) {
            ob_start();
            $output .= get_template_part( 'template-parts/content/training' );
            $output .= ob_get_clean();
        }

        $i++;
    }

    $output .= '</section>';

    return $output;

}

Enqueue editor script:

add_action( 'enqueue_block_editor_assets', 'load_editor_scripts' );

public function load_editor_scripts() {
    wp_enqueue_script( 'sm_editor_script', get_template_directory_uri() . '/assets/dist/js/editor.js', array(
        'wp-blocks',
        'wp-i18n',
        'wp-editor',
        'wp-components',
        'wp-block-editor'
    ), '1.0.0', true );
    wp_localize_script( 'sm_editor_script', 'gutenbergBlocks', array( 'themeUrl' => get_template_directory_uri() ) );
    }

What am I missing?

Upvotes: -1

Views: 1222

Answers (1)

maja
maja

Reputation: 175

I know :)

Two things:

  1. It should be:
<ServerSideRender
    block="mysite/trainings"
    attributes={ { postsCount } }
 />

(without default value here)

  1. If attribute is number, you have to ensure that it will be saved as number.

In js change in onChange function:

<NumberControl
    value={ postsCount }
    onChange={ ( value ) => setAttributes( { postsCount: Number.parseInt( value ) } ) }
    min={ 1 }
    max={ 9 }
/>

and in php render_trainings_block function:

$attributes['postsCount'] = (int) $attributes['postsCount'];

Upvotes: 1

Related Questions