Question

I could not get to work. When published the content the attribute innerContent didn't save. Here is what I tried.

block.js

//  Import CSS.
import './style.scss';
import './editor.scss';

const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
const { RichText } = wp.editor;

registerBlockType( 'hall/block-server-side-render', {
    title: __( 'Server Side Rendering' ),
    icon: 'shield',
    category: 'common',
        keywords: [
        __( 'Server Side Rendering' )
    ],
    attributes: {
      innerContent: {
          type: 'array',
              source: 'children',
              selector: 'p'
      }
    },
   edit: function( props ) {
       function onChangeContent( content ) {
            props.setAttributes( { innerContent: content } );
        }

    return (
        <div className={ props.className }>
                   <div class="gray-bg">
                      <RichText tagName="p" role="textbox" aria-multiline="true" value={props.attributes.innerContent} onChange={onChangeContent} />
                   </div>
        </div>
        );
    },
    save: function( props ) {
        return null;
    },
} );

init.php

register_block_type( 'hall/block-server-side-render', array(
    'render_callback' => 'hall_render_inner_content',
    'attributes' => array(
        'innerContent' => array(
            'type' => 'array'
        )
    )
));

function hall_render_inner_content( $attributes ) {
    $innerContent = $attributes['innerContent'];
    return '<div class="inner-content">' . $innerContent . '</div>';
}
Was it helpful?

Solution

Short Answer: When saving an attribute, always respect the attribute type. So if your attribute is of the array type, then save the value as an array, e.g. props.setAttributes( { innerContent: [ content ] } ).

Longer Answer

  1. Your register_block_type() call is missing the editor_script parameter. See the block editor handbook for details, but basically, you would need something like:

    function hall_register_block() {
        wp_register_script(
            'hall-block-server-side-render',
            '/path/to/block.js',
            array( 'wp-i18n', 'wp-blocks', 'wp-block-editor' ),
            '1.0'
        );
    
        register_block_type( 'hall/block-server-side-render', array(
            'render_callback' => 'hall_render_inner_content',
            'attributes'      => array(
                'innerContent' => array(
                    'type'    => 'array',
                    // You should set a default value:
                    'default' => array(), // if the attribute is an array
    //              'default' => '',      // if the attribute is a string
                ),
            ),
            // Here, your code is missing the block's script:
            'editor_script'   => 'hall-block-server-side-render',
        ) );
    }
    add_action( 'init', 'hall_register_block' );
    
  2. You defined the innerContent attribute as an array, so you would need to save it (via the props.setAttributes()) as an array:

    function onChangeContent( content ) {
        // Save the value as an array.
        props.setAttributes( { innerContent: [ content ] } );
    }
    

    And omit the attribute's source and selector properties so that the attributes would be saved to (and read from) the block's comment delimiter.

    attributes: {
        innerContent: {
            type: 'array',
            // No need for these two:
    //      source: 'children',
    //      selector: 'p'
        }
    },
    

    But then, in your block render callback (hall_render_inner_content()), you would also need to parse the HTML in the attribute value (which is not a simple array such as [ 'HTML here', 'another HTML here', 'etc etc' ]), and note that, in that callback, the $content is (or would supposedly be) an array and not a string.

    So you should probably just change the attribute type to string, i.e. just change the above type: 'array', to type: 'string',. And that way, you wouldn't need to save the attribute as an array.

  3. You should import RichText from wp.blockEditor and not wp.editor:

    const { RichText } = wp.blockEditor; // use this
    const { RichText } = wp.editor;      // not this
    

OTHER TIPS

You should be using string as attribute type, as in previous answer, and possibly set multiline attribute to true on Richtext and use multiline parameter in attributes, as explained here. https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#html

If you will be using multiline, be sure to set 'div.gray-bg' as selector in your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top