0

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>';
}
2
  • You made a typo here (in onChangeContent()): props.attributes( - and that should be props.setAttributes(..
    – Sally CJ
    Commented Mar 25, 2021 at 18:50
  • @SallyCJ, made the correction, edited the question, but it still didn't work. Commented Mar 25, 2021 at 19:39

2 Answers 2

0

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
    
1
  • PS: Sorry, I meant $innerContent and not $content.. :)
    – Sally CJ
    Commented Mar 25, 2021 at 23:22
0

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.

2
  • If the source is html, then the block's save() function would need to return an element, but I believe that's not the case with the block in question where the output is rendered on the server-side, hence the save() function should return null. But if we just want a p on pressing the "Enter" key, then we would set the multiline property in RichText to true.
    – Sally CJ
    Commented Mar 25, 2021 at 23:19
  • Yes, you are right if source is html and multiline is not set, Enter key creates <br> tag
    – Lovor
    Commented Mar 26, 2021 at 15:13

Your Answer

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

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