Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic block documentation #4067

Merged
merged 6 commits into from Dec 19, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
119 changes: 119 additions & 0 deletions docs/blocks-dynamic.md
@@ -0,0 +1,119 @@
# Creating dynamic blocks

It is possible to create dynamic blocks. These are blocks that can change their content even if the post is not saved. One example from WordPress itself is the latest posts block. This block will update everywhere it is used when a new post is published.

The following code example shows how to create the latest post block dynamic block.

{% codetabs %}
{% ES5 %}
```js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per consistency with other docs, should we include ES5 and ESNext varieties here?

// myblock.js

var el = wp.element.createElement,
registerBlockType = wp.blocks.registerBlockType,
withAPIData = wp.components.withAPIData;

registerBlockType( 'my-plugin/latest-post', {
title: 'Latest Post',
icon: 'megaphone',
category: 'widgets',

edit: withAPIData( function() {
return {
posts: '/wp/v2/posts?per_page=1'
};
} )( function( props ) {
if ( ! props.posts.data ) {
return "loading !";
}
if ( props.posts.data.length === 0 ) {
return "No posts";
}
var className = props.className;
var post = props.posts.data[ 0 ];

return el(
'a',
{ className: className, href: post.link },
post.title.rendered
);
} ),

save: function() {
// Rendering in PHP
return null;
},
} );
```
{% ESNext %}
```js
// myblock.js

const { el } = wp.element;
const { registerBlockType } = wp.blocks;
const { withAPIData } = wp.components;

registerBlockType( 'my-plugin/latest-post', {
title: 'Latest Post',
icon: 'megaphone',
category: 'widgets',

edit: withAPIData( () => {
return {
posts: '/wp/v2/posts?per_page=1'
};
} )( ( { posts, className } ) => {
if ( ! posts.data ) {
return "loading !";
}
if ( posts.data.length === 0 ) {
return "No posts";
}
var post = posts.data[ 0 ];

return <a className={ className } href={ post.link }>
{ post.title.rendered }
</a>;
} ),

save() {
// Rendering in PHP
return null;
},
} );
```
{% end %}

Because it is a dynamic block it also needs a server component. The rendering can be added using the `render_callback` property when using the `register_block_type` function.

```php
<?php
// block.php

function my_plugin_render_block_latest_post( $attribites ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: $attribites -> $attributes

Should we omit this if it's an unused variable?

$recent_posts = wp_get_recent_posts( array(
'numberposts' => 1,
'post_status' => 'publish',
) );
if ( count( $recent_posts ) === 0 ) {
return 'No posts';
}
$post = $recent_posts[ 0 ];
$post_id = $post['ID'];
return sprintf(
'<a class="wp-block-my-plugin-latest-post" href="%1$s">%2$s</a>',
esc_url( get_permalink( $post_id ) ),
esc_html( get_the_title( $post_id ) )
);
}

register_block_type( 'my-plugin/latest-post', array(
'render_callback' => 'my_plugin_render_block_latest_post',
) );
```

There are a few things to notice:

* The edit function still shows a representation of the block in the editor's context (this could be very different from the rendered version, it's up to the block's author)
* The save function just returns null because the rendering is performed server-side.
* The server-side rendering is a function taking the block attributes as an argument and returning the markup (quite similar to shortcodes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to be clearer about how attributes are also defined on the server for this to work correctly? Though in this case there are no attributes for this block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, I've copied these points from Riad's post. Could we merge this and iterate on it further?

6 changes: 6 additions & 0 deletions docs/manifest.json
Expand Up @@ -59,6 +59,12 @@
"markdown_source": "https:\/\/raw.githubusercontent.com\/WordPress\/gutenberg\/master\/docs\/blocks-controls.md",
"parent": "blocks"
},
{
"title": "Creating dynamic blocks",
"slug": "creating-dynamic-blocks",
"markdown_source": "https:\/\/raw.githubusercontent.com\/WordPress\/gutenberg\/master\/docs\/blocks-dynamic.md",
"parent": "blocks"
},
{
"title": "Reference",
"slug": "reference",
Expand Down