3

I am using custom block to generate shotcode that then renders the HTML.

When I add the block and save the post, everything works, the block renders the shortcode with its default values.

When I change some values, the post saves without error and works on frontend.

But when I reload the posts edit page I get the following error:

Block validation: Block validation failed for `fare/list-posts` ( 
Object { name: "fare/list-posts", icon: {…}, attributes: {…}, keywords: [],   save: save(t), title: "List Posts", category: "common", edit: edit(e)
 }
).

Content generated by `save` function:

[list-posts type="post" category="" count="6"][/list-posts]

Content retrieved from post body:

[list-posts type="post" category="" count="12"][/list-posts]

The validation expects default values but gets the new edited shortcode with new values.

Here is my JavaScript code:

/* This section of the code registers a new block, sets an icon and a category, and indicates what type of fields it'll include. */
wp.blocks.registerBlockType('fare/list-posts', {
  title: 'List Posts',
  icon: 'tickets',
  category: 'common',
  attributes: {
    posttype: {
      type: 'string',
      default: 'post'
    },
    postcategory: {
      type: 'string',
      default: ''
    },
    postcount: {
      type: 'number',
      default: 6
    },
  },

  /* This configures how the content and color fields will work, and sets up the necessary elements */
  edit: function(props) {
    function updatePostType(event) {
      props.setAttributes({posttype: event.target.value})
    }
    function updateCategory(event) {
      props.setAttributes({postcategory: event.target.value})
    }
    function updatePostCount(event) {
      props.setAttributes({postcount: event.target.value})
    }
    return React.createElement("div",{ style: { border: '2px solid #aaaaaa', 'border-radius': '3px', padding: '12px'}},
      React.createElement( "h3", null, "List Posts" ),
      React.createElement( "span", { style: { margin: '0' }}, "Post Type" ),
      React.createElement( "input", { type: "text", value: props.attributes.posttype, onChange: updatePostType, style: {} }),
      React.createElement( "hr" ),
      React.createElement( "span", { style: { margin: '0' }}, "Post Category" ),
      React.createElement( "input", { type: "text", value: props.attributes.postcategory, onChange: updateCategory, style: {} }),
      React.createElement( "hr" ),
      React.createElement( "span", { style: { margin: '0' }}, "Post Count" ),
      React.createElement( "input", { type: "number", value: props.attributes.postcount, onChange: updatePostCount, style: {} })
    )
  },

  save: function(props) {
    //
    return '[list-posts type="'+props.attributes.posttype+'" category="'+props.attributes.postcategory+'" count="'+props.attributes.postcount+'"][/list-posts]';
  }
})

Can someone please tell me what am I doing wrong?

Thank you.

6

In short, when saving an attribute, make sure its type matches the one that you defined in the block's attributes option.

The docs says:

Lastly, make sure that you respect the data’s type when setting attributes, as the framework does not automatically perform type casting of meta. Incorrect typing in block attributes will result in a post remaining dirty even after saving (cf. isEditedPostDirty, hasEditedAttributes). For instance, if authorCount is an integer, remember that event handlers may pass a different kind of data, thus the value should be cast explicitly:

function onChange( event ) {
  props.setAttributes( { authorCount: Number( event.target.value ) } );
}

So the problem is with the postcount attribute, which is defined as a number, yet saved as a string (event.target.value, in your case, is a string).

And with your code now, if you set the postcategory to foo and the postcount to something else than 6, e.g. 3, the block HTML output would be:

<!-- wp:fare/list-posts {"postcategory":"foo"} -->
[list-posts type="post" category="foo" count="3"][/list-posts]
<!-- /wp:fare/list-posts -->

but it should actually be — note the "postcount":3:

<!-- wp:fare/list-posts {"postcategory":"foo","postcount":3} -->
[list-posts type="post" category="foo" count="3"][/list-posts]
<!-- /wp:fare/list-posts -->

And here's the problematic code:

// In updatePostCount()
props.setAttributes({postcount: event.target.value})

which should be written as:

props.setAttributes({postcount: Number( event.target.value )})

I.e. You need to explicitly cast the value to a number and not passing the value as-is (a string).

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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