Before rendering a page, WordPress first generates the output for all blocks without actually printing them. When using a Query Loop, during each "loop cycle" WordPress generates the block code for each loop item using its render_block()
function. Here, we still have access to the "current" post, however, the issue is that WordPress does not process shortcodes in its render function. Instead, shortcodes are only processed when the full page content is outputted (composed of the previously rendered blocks). By that point, the shortcodes will no longer have access to their corresponding post but instead will refer to the current post, which is the rendered page itself.
TL;DR:
1 ) Copy the JS code and upload it to the server (e.g., in a child theme or add it to the site in any way, but ensure it loads on the block editor page!). 2 ) Copy the PHP code and add it to the site as custom code (using a plugin or in the child theme's PHP file). If you load the JS file with this PHP code, make sure to set its URL and PATH correctly. If not, remove that code part.
Detailed Description:
I was looking for a solution that doesn't require "hacking" the basic functionality of WordPress, is lightweight, universal, easy to use, and configurable, while also ensuring everything works as originally intended where this solution isn't needed. I found the solution on the PHP side using the render_block
hook, and on the block editor side through filters that allow custom attributes to be added by block type.
First, we need to add a new block attribute (let's call it "forceShortcodes") to the block types where shortcodes might appear. This should be set individually for each block in the block editor from the sidebar, ideally placed at the bottom of the sidebar in the "Advanced" section. Thanks to this, we can set the "forceShortcodes" custom attribute for any block, for example, those used in a query loop for displaying shortcodes. Then, we need to hook into the render_block filter and check if the currently rendered block has "forceShortcodes" enabled. If it does, we process the shortcode immediately and return the block's content this way.
Below you will find two files necessary for this solution.
- The JS file is complete and will work as it is. If you want to make any changes, you can find a "Basic config" section at the beginning of the JS code, where you can adjust the name of the parameter used (default is "forceShortcodes") and the text displayed in the sidebar control box. If you change the "attributeName" make sure to also change it in the PHP code. Below that, there is an "Advanced config" section. Here you can change the attribute control box location (by default, on the bottom of the sidebar in "Advanced" group or a separate custom control box). More importantly, here you can configure which block types can have the forced shortcode rendering mode set. By default, I've enabled it for all core WordPress blocks in the "Text" group. If you want to change this or also enable it for your own custom block types, I've included instructions as comments in the file on how to make these changes in seconds.
- In the PHP file, you only have to change the URL and the PATH of the JavaScript file if you want to load it with this PHP code. Also, if you changed the "attributeName" in the JS, make sure to change it accordingly here too.
Please, if you encounter any issues with the code's functionality despite following the steps, or if you have any suggestion for improvement, let me know in the comments!
I see, thanks for the screenshot! On your image, currently the Query Loop is selected, but you have to enable the added "Force Render" feature on a block, that actually contains the shortcode. As you can see in the Usage description, by default I've enabled the feature for all blocks in the "text" category (with variable name:
addToBlocks
) and additionally for the "core/shortcode" block (inaddToCustomBlocks
variable). It is good that you pointed out that the "core/html" can also contain shortcodes, I will update my gist soon to include it too! Until then, you can update theaddToCustomBlocks
manually to this:This way, the "Force Render" feature will be enabled for HTML blocks too and hopefully, you will be able to use it with your HTML blocks inside the Post Template.
Please let me know if it works or not!