0
votes

I added two RichText components in my block.

registerBlockType( 'hallmark/gray-content-container', {
        title: __( 'Gray Content Container' ),
        icon: 'grid-view',
        category: 'hallmark-blocks',
        keywords: [
            __( 'Hallmark gray content' ),
            __( 'Hallmark' ),
            __( 'Gray content container' ),
        ],

        attributes:{
            contentHeading: {
                type: 'string',
                source: 'children',
                selector: 'h1,h2,h3,h4,h5,h6'
            },
            textContent: {
                type: 'string'
            }
        },

        edit: function( props ) {

            var textContent = props.attributes.textContent;
            var contentHeading = props.attributes.contentHeading;

            function onChangeTextContent( content ) {
                props.setAttributes( { textContent: content } );
            }

            function onChangeHeading (heading) {
                props.setAttributes( { contentHeading: heading} );
            }

            return (
                <div className={ props.className }>
                    <label className="editor-content-section-label">Content for gray section</label>
                    <RichText
                        tagName="h1"
                        value={contentHeading}
                        onChange={onChangeHeading}
                        placeholder={ __( 'Add a heading' ) }
                        keepPlaceholderOnFocus
                    />
                    <RichText
                        tagName="p"
                        className={props.className}
                        onChange={onChangeTextContent}
                        value={textContent}
                        placeholder={ __( 'Add content' ) }
                        keepPlaceholderOnFocus
                    />
                </div>
            );
        },

        save: function( props ) {
            //return null;
            return(
                <div className={props.className}>
                    <div className="gray-bg">
                        <div className="constrain content">
                            <RichText.Content tagName="h1" value={ attributes.contentHeading } />
                            <RichText.Content tagName="p" value={ attributes.textContent } />
                        </div>
                    </div>
                </div>
            );

        },
    } );

I tried two different approaches to save the data.

Using default save() function

save: function( props ) {
      return(
         <div className={props.className}>
            <div className="gray-bg">
                <div className="constrain content">
                    <RichText.Content tagName="h1" value={ attributes.contentHeading } />
                    <RichText.Content tagName="p" value={ attributes.textContent } />
                 </div>
            </div>
         </div>
     );
},

Saving it in PHP:

Using render_callback method (Using return null; from block's default save() function.

register_block_type( 'hallmark/white-content-container', array(
    'render_callback' => 'hall_render_white_content'
) );

function hall_render_white_content( $atts ) {
   $heading = $atts['contentHeading'];
   $raw_content = $atts['textContent'];
   $full_content = $heading . $raw_content;
   // var_dump($full_content);

   $content = hall_clean_shortcode_block_content( $full_content );

   return '<div class="gray-bg"><div class="constrain content">' . $content . '</div></div>';
}

atts['contentHeading'] element does not exist at all in $atts array. When I check var_dump( $attas ); it has textContentelement present.

The problem is both approaches are only saving the textContent. contentHeading is not at all saving.

What I am missing?

2
For debugging use console.log(props.attributes) inside your edit function and observe if the values of contentHeading is changing or not when you edit. edit() function will be called each time if the state or props of component changes. As per my lucky guess the source of contentHeading should be 'text' instead of 'children'. - Mehmood Ahmad
You saved my life. Thank you so much @MehmoodAhmad :) - Subrata Sarkar
Glad to here that. Adding proper answer below for others please accept that so that it can help others. - Mehmood Ahmad
One question. I wanted it to save from server side using render_callback. My function is function hall_render_gray_content( $atts ) {...}. But it is never getting the value of $atts['contentHeading']; even when I have it. When I am trying this the red Publish error notification is coming up. What could be the reason? - Subrata Sarkar
Sorry I didn't work with serverSideRendering until now. I have find out that mostly we don't need serverSideRendering. So can you please explain why you are using that so that we can discuss whether you need that or not. We only need server side rendering when our live content changes with time like our latest posts if the content is static and we only need to edit it from back-end then there is no need for server side rendering. - Mehmood Ahmad

2 Answers

1
votes

Try setting

attributes:{ contentHeading: { type: 'string', source: 'children', selector: 'h1' }, textContent: { type: 'string' selector: 'p' } },

I think the selectors have to exactly match what is set in the save method.

<div className="constrain content"> <RichText.Content tagName="h1" value={ attributes.contentHeading } /> <RichText.Content tagName="p" value={ attributes.textContent } /> </div>

I think you also need a unique selector, so if you had two RichText paragraphs, you could do

textContentA: { type: 'string' selector: 'p.content-a' } textContentB: { type: 'string' selector: 'p.content-b' }

0
votes

For debugging use console.log(props.attributes) inside your edit function and observe if the values of contentHeading is changing or not when you edit. edit() function will be called each time if the state or props of component changes. As per my lucky guess the source of contentHeading should be 'text' instead of children.