Block editor link control for custom post types

The WordPress block editor supports a link picker that we can add to our custom blocks. The best bit is we can restrict its searches to a post type of our choosing.

Building WordPress websites since WordPress adopted the block editor can often mean building custom blocks. They’ve pretty much taken over the role that custom shortcodes filled in the world before blocks, which usually means a better build for clients, but sometimes means a tougher challenge for developers.

A fairly typical custom block for sites I’ve been building has included the following bits:

  • a title
  • an image
  • a blurb
  • a link

But sometimes, I don’t want just any old link; sometimes I want the client to pick links from a specific custom post type.

To add a link picker to our custom block, there’s a few different approaches we can take, but the nicest one I’ve found is to use the LinkControl component. Sadly, documentation of this component is… sparse? terse? enigmatic? Troublesome. Also, it seems to be stuck in a state of “experimental” so we need to jump the odd hoop to get it working.

First of all, we need to import it into our block with an alias, like this:

const {__experimentalLinkControl: LinkControl} = wp.blockEditor;

That lets us reference the control by its natural, non-experimental name. By default, it will then search all available post types as we type in a name, but of course we want to restrict it.

<LinkControl
  value={ { url: attributes.link, title: attributes.link_title } }
  onChange={ ( value ) => {
    setAttributes({ link: value.url, link_title: value.title })
  }}
  settings={ [] }
  suggestionsQuery={ { type: "post", subtype: "wpwines_product" } }
/>

The trick here is to pass it an object describing what we want it to search for. There’s a few types of objects it can search, of which we want “post”, and within that we can ask for a specific subtype being our custom post type.

The parameter to use here is suggestionsQuery. What does the documentation say about that? “See above”, so after scanning the ceiling a bit we end up having a crack at a few things ultimately culminating in giving it an object with a type of “post” and a subtype of our custom post type.

Another thing that we might want to change is whether it shows a toggle for opening the link in a new tab. If we’re asking it to only show posts from a specific custom post type, there’s a high probability we don’t want that toggle! Passing an empty array to the settings parameter does that.

The value passed to and from the component is an object with a few pieces but importantly it has a URL member and a title member. We can store those in our block’s attributes and pass them back to the component when editing it.

Put it all together, and we have a link picker in our block that only offers posts from our custom post type as suggestions.

NB: our custom post type will only show in link suggestions if we register it with show_in_rest! Which makes sense, really; the suggestions are found via REST requests.

Job is done, after perhaps a little too much hunting through source code and inspecting REST JSON requests.