I have a block that renders titles of all existing posts in the <Modal/>
. I retrieve it from the server using <ServerSideRender/>
(that returns plain html). I want to be able to choose one of the titles (ideally save it in the postTitle
attribute) and display it in the block.
attributes: {
postTitle: {
type: 'string'
}
},
edit(props) {
const { attributes } = props;
const { postTitle } = props.attributes;
const MyModal = withState( {
isOpen: false,
} )
( ( { isOpen, setState } ) => (
<div>
<Button isDefault onClick={ () => setState( { isOpen: true } ) }>Choose</Button>
{ isOpen ?
<Modal onRequestClose={ () => setState( { isOpen: false } ) }>
<ServerSideRender
block="my-blocks/wordpress-title"
attributes={attributes}
/>
</Modal>
: null }
</div>
) );
return ([
<InspectorControls>
<div>
<strong>Choose Wordpress title:</strong>
<MyModal/>
</div>
</InspectorControls>,
]);
},
Is there any sensible way to retrieve data from a server, so it was possible to operate on it within a block?
I have a block that renders titles of all existing posts in the <Modal/>
. I retrieve it from the server using <ServerSideRender/>
(that returns plain html). I want to be able to choose one of the titles (ideally save it in the postTitle
attribute) and display it in the block.
attributes: {
postTitle: {
type: 'string'
}
},
edit(props) {
const { attributes } = props;
const { postTitle } = props.attributes;
const MyModal = withState( {
isOpen: false,
} )
( ( { isOpen, setState } ) => (
<div>
<Button isDefault onClick={ () => setState( { isOpen: true } ) }>Choose</Button>
{ isOpen ?
<Modal onRequestClose={ () => setState( { isOpen: false } ) }>
<ServerSideRender
block="my-blocks/wordpress-title"
attributes={attributes}
/>
</Modal>
: null }
</div>
) );
return ([
<InspectorControls>
<div>
<strong>Choose Wordpress title:</strong>
<MyModal/>
</div>
</InspectorControls>,
]);
},
Is there any sensible way to retrieve data from a server, so it was possible to operate on it within a block?
Share Improve this question edited Sep 16, 2018 at 14:00 Michal Karbownik asked Sep 5, 2018 at 22:14 Michal KarbownikMichal Karbownik 1314 bronze badges 4- 1 I had a little trouble following your description, can you edit your question to include a real world example I can relate to? It wasn't clear, and some terms you used didn't seem to make sense in context, e.g. inspector. Perhaps if you explained what you were trying to do without making it super generic it would be more understandable? – Tom J Nowell ♦ Commented Sep 5, 2018 at 23:26
- @TomJNowell Thank you for the advice. Is it clearer now? – Michal Karbownik Commented Sep 6, 2018 at 21:20
- Why do you render my-blocks/wordpress-title on the serverside? The Gutenberg handbook states: << ServerSideRender should be regarded as a fallback or legacy mechanism, it is not appropriate for developing new features against.>> Why can't you get the list of posts through the WP REST api? – Andrei Draganescu Commented Feb 21, 2019 at 21:11
- @AndreiDraganescu That was mostly an 'art for art's sake' type of exercise. The goal was to create a dynamic block using the server-side rendering. Thus the question about doing it this way. – Michal Karbownik Commented Feb 22, 2019 at 8:44
1 Answer
Reset to default 1There are multiple better ways to get a list of posts in a Gutenberg block, other than rendering serverside.
First is to use the Wrodpress wrapper around Redux and select posts exactly like in the Gutenberg Handbook:
edit: withSelect( function( select ) {
return {
posts: select( 'core' ).getEntityRecords( 'postType', 'post' )
};
} )( function( props ) {
if ( ! props.posts ) {
return "Loading...";
}
if ( props.posts.length === 0 ) {
return "No posts";
}
var className = props.className;
var post = props.posts[ 0 ];
return el(
'a',
{ className: className, href: post.link },
post.title.rendered
);
} ),
Notice how the edit function is composed with data from the Gutenberg store and it gets the posts array as a prop.
The second option is to simply use Axios to get the posts you need via the rest API:
/**
* Makes a get request to the desired post type and builds the query string based on an object.
*
* @param {string|boolean} restBase - rest base for the query.
* @param {object} args
* @returns {AxiosPromise<any>}
*/
export const getPosts = ({ restBase = false, ...args }) => {
const queryString = Object.keys(args).map(arg => `${arg}=${args[arg]}`).join('&');
return axios.get(`/wp-json/wp/v2/${restBase}? ${queryString}&_embed`);
};
This is a snippet from this great tutorial: https://github/bigbitecreative/gutenberg-postlist-demo
After the posts call is defined you may use componentDidMount to call it and then set the posts as the new Modal componenet state:
/**
* When the component mounts it calls this function.
* Fetches posts types, selected posts then makes first call for posts
*/
componentDidMount() {
this.setState({
loading: true,
});
api.getPostTypes()
.then(({ data = {} } = {}) => {
this.setState({
types: data
}
});
}
Also from Gutenberg Postlist demo but shortened for brevity.