-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Experiment: Live Block #38829
Experiment: Live Block #38829
Conversation
@@ -49,10 +49,17 @@ function render_block_core_query_pagination_next( $attributes, $content, $block | |||
$custom_query = new WP_Query( build_query_vars_from_query_block( $block, $page ) ); | |||
$custom_query_max_pages = (int) $custom_query->max_num_pages; | |||
if ( $custom_query_max_pages && $custom_query_max_pages !== $page ) { | |||
$data_attributes = sprintf( | |||
'data-block="%1$s" data-attribute="%2$s" data-new-value="%3$s"', | |||
'core/query', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assumption is that the block that controls the interaction (here: pagination; could also be some other interaction, such as a filter) lives inside of the block that renders the thing that we want to change (here: the list of posts). We're specifying the type of that ancestor block here so that it can be located by the client-side logic that is going to replace its content.
Size Change: +347 B (0%) Total Size: 1.15 MB
ℹ️ View Unchanged
|
const blockSelector = `.wp-block-${ blockName.replace( 'core/', '' ) }`; // TODO: Need a better mechanism here. | ||
|
||
// Fetch the HTML of the new block. | ||
// TODO: Need to include blocks' current attributes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those attributes are well-known and serialized (as part of the Gutenberg block delimiting comment <!-- wp:something ... -->
). We need to expose them here on the frontend.
Fetching from the I wonder if that's because the block type is actually part of the route ( FWIW, the issue doesn't seem to be related to authentication (or lack thereof), though that might present a problem later. Hopefully just a technicality though, it seems like we should be able to render most blocks in a |
Meh, maybe it's because the Query block isn't really a "proper" dynamic block but accepts inner blocks that really determine how it's rendered 🤔 I wonder if/how we can (and should?) bend that to be able to have it rendered by the endpoint. |
Decided to use the calendar block for a proof-of-concept 😬 |
Nice work! I've been working on a similar idea in #38843 ! 🙂 |
3e1af6e
to
f2cf253
Compare
f2cf253
to
fa3e3ec
Compare
The latest commit requires the following patch against Core: diff --git a/wp-includes/class-wp-block.php b/wp-includes/class-wp-block.php
index 90148f7613..37eb60ddd7 100644
--- a/wp-includes/class-wp-block.php
+++ b/wp-includes/class-wp-block.php
@@ -190,6 +190,17 @@ class WP_Block {
return null;
}
+ public function render_attributes( $attrs ) {
+ $result = '';
+ foreach ( $attrs as $key => $value) {
+ if ( is_array( $value ) ) {
+ $value = json_encode( $value ); // TODO: Encode
+ }
+ $result .= 'data-' . _wp_to_kebab_case( $key ) . "='" . $value ."' ";
+ }
+ return $result;
+ }
+
/**
* Generates the render output for the block.
*
@@ -214,6 +225,10 @@ class WP_Block {
$is_dynamic = $options['dynamic'] && $this->name && null !== $this->block_type && $this->block_type->is_dynamic();
$block_content = '';
+ $block_content .= '<wp-block type="' . $this->name . '" ';
+ $block_content .= $this->render_attributes( $this->attributes );
+ $block_content .= '>';
+
if ( ! $options['dynamic'] || empty( $this->block_type->skip_inner_blocks ) ) {
$index = 0;
@@ -259,6 +274,8 @@ class WP_Block {
$post = $global_post;
}
+ $block_content .= '</wp-block>';
+
if ( ! empty( $this->block_type->script ) ) {
wp_enqueue_script( $this->block_type->script );
}
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php
index 3e4e8eb794..9bca0ae316 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php
@@ -126,15 +126,15 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller {
);
}
} else {
- if ( ! current_user_can( 'edit_posts' ) ) {
- return new WP_Error(
- 'block_cannot_read',
- __( 'Sorry, you are not allowed to read blocks as this user.' ),
- array(
- 'status' => rest_authorization_required_code(),
- )
- );
- }
+ // if ( ! current_user_can( 'edit_posts' ) ) {
+ // return new WP_Error(
+ // 'block_cannot_read',
+ // __( 'Sorry, you are not allowed to read blocks as this user.' ),
+ // array(
+ // 'status' => rest_authorization_required_code(),
+ // )
+ // );
+ // }
}
return true;
@@ -165,7 +165,7 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller {
$registry = WP_Block_Type_Registry::get_instance();
$registered = $registry->get_registered( $request['name'] );
- if ( null === $registered || ! $registered->is_dynamic() ) {
+ if ( null === $registered ) {
return new WP_Error(
'block_invalid',
__( 'Invalid block.' ),
|
TODO/Next stept: Properly encode nested args ( See e.g. gutenberg/packages/server-side-render/src/test/index.js Lines 29 to 40 in 7fc0147
|
Punting this experiment for now. I have a short, tentative, TODO list/roadmap for potential next steps; however, note the one major problem described below the list.
The major problem: Even if we implement all of the above, one issue remains: A (static) parent block -- such as the Query block we're using in this experiment -- typically has a lot of nested content (typically inner/child blocks). This means that block "properties" and content aren't just specified via block attributes and context, but also through the nested content. Following the paradigm explored in this PR, where we're sending all block attributes (and context) to the We might at that point consider alternatives, such as uniquely identifying every block in a site with a unique ID, as we're already somehow doing with It's however arguable that maybe this presents too much overhead, and we'd be better suited with a "full-page" based approach such as demonstrated in #38713. |
Description
WIP. Experiment, based on @michalczaplinski's #38713.
Currently using the Calendar block since I couldn't get the Query block to work with the
block-renderer
endpoint (see comments below).The idea is to replace a block in the markup with a server-rendered block (fetched from the
block-renderer
endpoint), to avoid server-rendering an entire page and extracting the relevant markup from it.Testing Instructions
Use the Twenty Twenty Two theme. Make sure you have a sizable number of posts (you can use
wp post generate --count=30
to auto-generate them.)On the frontpage, click the "Next" pagination link at the bottom, and observe the network tab. It should fetch the Calendar block and replace the Post Query block with it 😬
Screenshots
Types of changes
Experiment/demo