admin管理员组

文章数量:1394079

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.

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.

Share Improve this question asked Feb 14, 2020 at 8:50 VincurekfVincurekf 1231 gold badge2 silver badges8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 13

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).

本文标签: Gutenberg Block validation failed