Last active
June 16, 2022 00:44
-
-
Save igorbenic/2f92aa2bd5512a6eb49f93fd9e8e9481 to your computer and use it in GitHub Desktop.
How to create a Gutenberg Block for Displaying a Post | https://www.ibenic.com/create-gutenberg-block-displaying-post/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
registerBlockType( 'cgb/block-guten-load-post', { | |
// ... | |
keywords: [ | |
__( 'my-block — CGB Block' ), | |
__( 'CGB Example' ), | |
__( 'create-guten-block' ), | |
], | |
attributes: { | |
content: { | |
type: 'array', | |
source: 'children', | |
selector: 'p', | |
}, | |
title: { | |
type: 'string', | |
selector: 'h2' | |
}, | |
link: { | |
type: 'string', | |
selector: 'a' | |
}, | |
selectedPost: { | |
type: 'number', | |
default: 0, | |
}, | |
}, | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... | |
const { __ } = wp.i18n; // Import __() from wp.i18n | |
const { registerBlockType, InspectorControls } = wp.blocks; // Import registerBlockType() from wp.blocks | |
const { SelectControl } = wp.components; | |
const { Component } = wp.element; | |
class mySelectPosts extends Component { | |
render() { | |
return ( 'Load Post Placeholder' ) | |
} | |
} | |
registerBlockType( 'cgb/block-guten-load-post', { | |
// ... | |
// The "edit" property must be a valid function. | |
edit: mySelectPosts, | |
// ... | |
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class mySelectPosts extends Component { | |
// Method for setting the initial state. | |
static getInitialState( selectedPost ) { | |
return { | |
posts: [], | |
selectedPost: selectedPost, | |
post: {}, | |
}; | |
} | |
// Constructing our component. With super() we are setting everything to 'this'. | |
// Now we can access the attributes with this.props.attributes | |
constructor() { | |
super( ...arguments ); | |
// Maybe we have a previously selected post. Try to load it. | |
this.state = this.constructor.getInitialState( this.props.attributes.selectedPost ); | |
} | |
render() { | |
// Options to hold all loaded posts. For now, just the default. | |
let options = [ { value: 0, label: __( 'Select a Post' ) } ]; | |
return [ | |
// If we are focused on this block, create the inspector controls. | |
!! this.props.isSelected && ( <InspectorControls key='inspector'> | |
<SelectControl | |
// Selected value. | |
value={ this.props.attributes.selectedPost } | |
label={ __( 'Select a Post' ) } | |
options={ options } /> | |
</InspectorControls> | |
), | |
'Load Post Placeholder' | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class mySelectPosts extends Component { | |
// ... | |
render() { | |
let options = [ { value: 0, label: __( 'Select a Post' ) } ]; | |
let output = __( 'Loading Posts' ); | |
if( this.state.posts.length > 0 ) { | |
const loading = __( 'We have %d posts. Choose one.' ); | |
output = loading.replace( '%d', this.state.posts.length ); | |
this.state.posts.forEach((post) => { | |
options.push({value:post.id, label:post.title.rendered}); | |
}); | |
} else { | |
output = __( 'No posts found. Please create some first.' ); | |
} | |
return [ | |
!! this.props.isSelected && ( <InspectorControls key='inspector'> | |
<SelectControl value={ this.props.attributes.selectedPost } label={ __( 'Select a Post' ) } options={ options } /> | |
</InspectorControls> | |
), | |
output | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class mySelectPosts extends Component { | |
// ... | |
constructor() { | |
super( ...arguments ); | |
this.state = this.constructor.getInitialState( this.props.attributes.selectedPost ); | |
// Bind so we can use 'this' inside the method. | |
this.getOptions = this.getOptions.bind(this); | |
// Load posts. | |
this.getOptions(); | |
} | |
/** | |
* Loading Posts | |
*/ | |
getOptions() { | |
return ( new wp.api.collections.Posts() ).fetch().then( ( posts ) => { | |
if( posts && 0 !== this.state.selectedPost ) { | |
// If we have a selected Post, find that post and add it. | |
const post = posts.find( ( item ) => { return item.id == this.state.selectedPost } ); | |
// This is the same as { post: post, posts: posts } | |
this.setState( { post, posts } ); | |
} else { | |
this.setState({ posts }); | |
} | |
}); | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class mySelectPosts extends Component { | |
// ... | |
constructor() { | |
// ... | |
// Bind it. | |
this.onChangeSelectPost = this.onChangeSelectPost.bind(this); | |
} | |
onChangeSelectPost( value ) { | |
// Find the post | |
const post = this.state.posts.find( ( item ) => { return item.id == parseInt( value ) } ); | |
// Set the state | |
this.setState( { selectedPost: parseInt( value ), post } ); | |
// Set the attributes | |
this.props.setAttributes( { | |
selectedPost: parseInt( value ), | |
title: post.title.rendered, | |
content: post.excerpt.rendered, | |
link: post.link, | |
}); | |
} | |
render() { | |
// ... | |
return [ | |
!! this.props.focus && ( <InspectorControls key='inspector'> | |
// Adding onChange method. | |
<SelectControl onChange={this.onChangeSelectPost} value={ this.props.attributes.selectedPost } label={ __( 'Select a Post' ) } options={ options } /> | |
</InspectorControls> | |
), | |
output | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class mySelectPosts extends Component { | |
render() { | |
let options = [ { value: 0, label: __( 'Select a Post' ) } ]; | |
let output = __( 'Loading Posts' ); | |
this.props.className += ' loading'; | |
if( this.state.posts.length > 0 ) { | |
// ... | |
} else { | |
output = __( 'No posts found. Please create some first.' ); | |
} | |
// Checking if we have anything in the object | |
if( this.state.post.hasOwnProperty('title') ) { | |
output = <div className="post"> | |
<a href={ this.state.post.link }><h2 dangerouslySetInnerHTML={ { __html: this.state.post.title.rendered } }></h2></a> | |
<p dangerouslySetInnerHTML={ { __html: this.state.post.excerpt.rendered } }></p> | |
</div>; | |
this.props.className += ' has-post'; | |
} else { | |
this.props.className += ' no-post'; | |
} | |
return [ | |
!! this.props.isSelected && ( <InspectorControls key='inspector'> | |
<SelectControl onChange={this.onChangeSelectPost} value={ this.props.attributes.selectedPost } label={ __( 'Select a Post' ) } options={ options } /> | |
</InspectorControls> | |
), | |
<div className={this.props.className}>{output}</div> | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
registerBlockType( 'cgb/block-guten-load-post', { | |
// ... | |
// The "save" property must be specified and must be a valid function. | |
save: function( props ) { | |
return ( | |
<div className={ props.className }> | |
<div className="post"> | |
<a href={ props.attributes.link }><h2 dangerouslySetInnerHTML={ { __html: props.attributes.title } }></h2></a> | |
<p dangerouslySetInnerHTML={ { __html: props.attributes.content } }></p> | |
</div> | |
</div> | |
); | |
}, | |
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
registerBlockType( 'cgb/block-guten-load-post', { | |
// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block. | |
title: __( 'Load a Post' ), // Block title. | |
icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/. | |
category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed. | |
keywords: [ | |
__( 'load' ), | |
__( 'Load Post' ), | |
__( 'guten-load-post' ), | |
], | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@keyframes pulse { | |
0% { | |
background-color: #ffffff; | |
} | |
50% { | |
background-color: #cccccc; | |
} | |
100% { | |
background-color: #ffffff; | |
} | |
} | |
.wp-block-cgb-block-guten-load-post { | |
padding: 0.5em; | |
border: 1px dashed rgba(0, 0, 0, 0.5); | |
&.no-post { | |
background: yellow; | |
animation: none; | |
} | |
&.loading { | |
animation: pulse 3s infinite; | |
} | |
&.has-post { | |
animation: none; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
InspectorControls has been moved from wp.blocks to wp.blockEditor