For a project I needed the feature to link posts of a custom post type with posts of another custom post type. I did not know which Gutenberg component would be the best match for that, but then the tags field for post tags seemed like a good fit: the user types something and gets suggestions which he can add to a selection.
The FormTokenField
can be used to create that behavior, all possible options can be found in the linked readme. With that, I had my component of choice, just with custom post type posts instead of tags.
That is how the component looks like as part of the project (code is reduced to a minimum):
// […]
// `posts` contains post objects from REST API call.
// `selectedPosts` contains array of currently selected post IDs.
let postNames = [];
let postFieldValue = [];
if ( posts !== null ) {
// Create post names array.
postNames = posts.map( ( post ) => post.title.raw );
// Create array of post titles that match the post IDs that are currently selected.
postFieldValue = selectedPosts.map( ( postId ) => {
let wantedPost = posts.find( ( post ) => {
return post.id === postId;
} );
if ( wantedPost === undefined || ! wantedPost ) {
return false;
}
return wantedPost.title.raw;
} );
}
const postsSelectComponent = <FormTokenField
label='Posts'
value={ postFieldValue }
suggestions={ postNames }
maxSuggestions={ 20 }
onChange={ ( selectedPosts ) => {
// Build array of selected posts.
let selectedPostsArray = [];
selectedPosts.map(
( postName ) => {
const matchingPost = posts.find( ( post ) => {
return post.title.raw === postName;
} );
if ( matchingPost !== undefined ) {
selectedPostsArray.push( matchingPost.id );
}
}
)
setAttributes( { selectedPosts: selectedPostsArray } );
} }
/>
Code language: JavaScript (javascript)
Because I do not want to show the post IDs as suggestions to the user, that are stored inside a meta value, but the title, it is a little more complex than the example in the readme. Starting at line 27, I need to convert the selected post title into the ID before saving it.
At the beginning of the code block instead, the IDs need to be converted to the titles for the suggestions list.
I created a Gist with a working code example.