admin管理员组

文章数量:1202780

In my pages, I have a number of custom blocks that allow you to select a page. In the save function, I save the pages URL.

    registerBlockType("djave/blockwithlink", {
        attributes: {
            page: {
                // { id: 1, url: "/page-url", title: "Page title"}
                type: "object",
                default: {},
            },
        },
        edit,
        save({attributes}){
          return (<div>
            <a href={attributes.link.url}>{attributes.link.title}</a>
          </div>)
        }
    });

This is great, when I save the block I get:

<div>
  <a href="/page-url">Page title</a>
</div>

But if the page is edited to /new-page-url, saved block has the out dated URL.

Is there a way to put a permalink to an ID into a save() function?

The other option I have is that I return null from the save function and instead create the template as PHP and use something like I'm used to from PHP templating like get_permalink($attributes['link']['id']).

However:

  1. have lots of blocks that follow the same pattern which would need to be extracted to PHP.
  2. I'm really enjoying using the save function, and don't like the idea of half of my blocks being JavaScript saved and half being PHP rendered, it seems wrong.

This feels like it must be a "solved" problem. Is there a Gutenberg way of doing this?

In my pages, I have a number of custom blocks that allow you to select a page. In the save function, I save the pages URL.

    registerBlockType("djave/blockwithlink", {
        attributes: {
            page: {
                // { id: 1, url: "http://site.dev/page-url", title: "Page title"}
                type: "object",
                default: {},
            },
        },
        edit,
        save({attributes}){
          return (<div>
            <a href={attributes.link.url}>{attributes.link.title}</a>
          </div>)
        }
    });

This is great, when I save the block I get:

<div>
  <a href="http://site.dev/page-url">Page title</a>
</div>

But if the page is edited to http://site.dev/new-page-url, saved block has the out dated URL.

Is there a way to put a permalink to an ID into a save() function?

The other option I have is that I return null from the save function and instead create the template as PHP and use something like I'm used to from PHP templating like get_permalink($attributes['link']['id']).

However:

  1. have lots of blocks that follow the same pattern which would need to be extracted to PHP.
  2. I'm really enjoying using the save function, and don't like the idea of half of my blocks being JavaScript saved and half being PHP rendered, it seems wrong.

This feels like it must be a "solved" problem. Is there a Gutenberg way of doing this?

Share Improve this question asked Mar 25, 2022 at 11:16 DjaveDjave 2584 silver badges25 bronze badges 2
  • "don't like the idea of half of my blocks being JavaScript saved and half being PHP rendered, it seems wrong" - that's just how dynamic blocks work, and if you want a guaranteed fresh permalink even if the post slug or permalink structure is changed later (outside or when not using the block editor), then a dynamic block would be what you need. – Sally CJ Commented Mar 31, 2022 at 3:04
  • But if just want your save() to always use the fresh post permalink, then just save the post ID as part of the attributes object and use the REST API to fetch the post permalink. And actually, I noticed an id in the page attribute, so you could just make use of that property. – Sally CJ Commented Mar 31, 2022 at 3:07
Add a comment  | 

1 Answer 1

Reset to default 1 +150

I think the issue you will run into here is that markup from the save function is created at post edit. The attributes like that link.url you reference will be correct at time of save - which is where the JS runs - but not necessarily at render if the post attributes have been changed.

The only way I can think of to change this at block render without PHP render would be to store your ID as a data-attribute against the anchor. Something like:

<a href="#" data-post-id="234" data-rest-route="posts">Link Content</a>

Where data-post-id is obviously the post ID and data-rest-route is the rest route or the parameter from the rest_base when you set up the posts with register_post_type() This you can parse from the initial post query return (the bit where you get the slug in your un-posted code to add to the .link.url on the block)

You can then run a secondary JS script on page load that leverages the REST API to get the correct slug at time of render.

Your URL path will be something like

/wp-json/wp/v2/{post_type}/{ID} or to match the above example /wp-json/wp/v2/posts/234

Then take the slug from the JSON object on page load to inject into the link href.

It's a bit of a workaround... And I wouldn't use this in public plugin code, as you have no idea how or if the rest API has been allowed or modified on custom post types for other setups.

本文标签: permalinksGutenberg output URL to post from attribute with post ID