Having Fun with Query Loop Block

The Query Loop block is a powerful tool that brings the WP Loop, a core WordPress function, to the block editor. Introduced in WordPress version 5.8 and continually updated and improved since then, the Query Loop block is a useful way to display a list of posts or other content in the block editor. In this article, we will explore the usefulness of the Query Loop block and how to extend its capabilities.

To get started, we will create a plugin to store our code. The quickest way to create a plugin scaffold is by using the WP-CLI command npx @wordpress/create-block loop-patterns, which will generate the necessary files for us.

If you want more information on the create-block script, you can check out the WordPress documentation.

Query Loop Variations

WordPress provides block variations as a way for developers to create custom versions of core blocks. To get started, we will need to create some directories to store our code. We can do this by running a few commands in the terminal.

We begin by creating a simple block variation called simple-query, and adding a CSS folder to store minimal styles. We don’t want to change the theme styles already declared in the theme.json file. To add our code, we will edit the simple-query/index.js file.

We will use the registerBlockVariation() function to register our block variation. If you are unfamiliar with block variations, you can learn more about them here.

This code defines a constant called SIMPLE_QUERY, which is set to the string 'loop-patterns/simple-query'. This constant represents the name of a block variation that is being registered.

The wp.domReady() function is a WordPress function that is called when the DOM (Document Object Model) is fully loaded and ready for manipulation. Inside the wp.domReady() function, the wp.blocks.registerBlockVariation() function is called with two arguments: 'core/query' and an empty object {}.

The wp.blocks.registerBlockVariation() function is used to register a block variation. The first argument is the name of the parent block (in this case, 'core/query'), and the second argument is an object that specifies the properties of the block variation being registered. In this case, the object is empty, so no additional properties are being set for the block variation.

As previously mentioned, the registerBlockVariation() function takes two arguments: the first argument is the name of the parent block, and the second argument is an object that specifies the properties of the block variation being registered. Let’s review the properties of the object.

  1. name: This property specifies the name of the block variation being registered. In this case, the value of the name property is the constant SIMPLE_QUERY, which represents the string 'loop-patterns/simple-query'.
  2. title: This property specifies the title of the block variation. This title will be displayed to the user in the block editor. In this case, the value of the title property is 'Simple Query'.
  3. description: This property specifies a description of the block variation. This description will be displayed to the user in the block editor. In this case, the value of the description property is 'Displays a Simple Query'.
  4. return: This property is a function that specifies the conditions under which the block variation should be displayed to the user. In this case, the function returns true if the namespace variable is equal to SIMPLE_QUERY and the query.postType variable is equal to 'post'. Otherwise, the function returns false.
  5. icon: This property specifies the icon that should be displayed for the block variation in the block editor. In this case, the value of the icon property is 'edit-large', which represents a pencil icon.
  6. attributes: This property is an object that specifies the attributes (i.e., data values) that the block variation should have. In this case, the object is empty, so no attributes are being set for the block variation.

Block Attributes

The next step will be adding our block attributes. Let’s take a look at the Query Loop block attributes.


Based on the screenshots, we can add the following to the attributes object in our script:

The attributes object in this code defines the query parameters that will be used to retrieve posts from the WordPress database.

Here is what each attribute does:

  • perPage: The number of posts to be displayed on each page.
  • pages: The number of pages to be displayed.
  • offset: The number of posts to skip before starting to display posts.
  • postType: The type of post to be displayed (e.g., post, page, etc.).
  • order: The order in which the posts will be displayed (either asc for ascending or desc for descending).
  • orderBy: The criteria used to order the posts (e.g., date, title, etc.).
  • author: The ID of the author whose posts will be displayed.
  • search: A search term used to filter the posts that are displayed.
  • exclude: An array of post IDs to exclude from the query.
  • sticky: A value used to include or exclude sticky posts from the query.
  • inherit: A boolean value indicating whether the query should inherit the context of the current page.

These attributes can be used to customize the behavior of the query and fine-tune which posts are displayed.

Finally, we will build our template. We can use the innerBlocks property to build our template by creating nested blocks within the parent block.

In this case, the innerBlocks array has three nested blocks:

  1. The first nested block is an instance of the core/post-template block, which is a template block that can be used to display a single post. The second element of the array is an empty object {}, which represents the attributes of the block. The third element of the array is another array, which represents the content of the block. In this case, the content of the core/post-template block consists of two blocks: the core/post-title block and the core/post-excerpt block.
  2. The second nested block is an instance of the core/query-pagination block, which is used to display pagination links for a list of posts.
  3. The third nested block is an instance of the core/query-no-results block, which is displayed when a query returns no results.

This is what our final code will look like::

Register Our Scripts

Now let’s test our simple query to make sure it is reading our code correctly. To do this, we need to change how we register our scripts in the **loop-patterns.php**file. Replace the existing content with the following:

To make sure you are calling the script correctly, add the following to the src/index.js file:

And make sure that you’re calling the script correctly on src/index.js. Add this:

Let’s visit the block editor and check out our new block variation. See how it appears in the block editor and on the frontend of the site.

While our custom variation is simple, it’s a good starting point. Now that we have a better understanding of how to register a query loop variation let’s create a flip cards variation for the Query Loop block. To create a new flip-cards variation, we can follow the same steps we used to create the previous variation.

This code registers a new block variation for the core/query block calledflip-cards. The variation has a name, title, and description and is only active if the namespace is FLIP_CARDS and the postType attribute of the query object is 'post'. The variation also has a set of attributes, including a className, tagName, and queryobject.

The variation is scoped to the block inserter and does not contain any inner blocks.

Inner Blocks

For our inner blocks, let’s do the following:

This code defines an array of inner blocks for the flip-cards variation of the core/query block. The inner blocks include a core/post-template block, which is locked and has a specific className. The core/post-template block also contains a core/group block, which in turn contains a core/columns block. The core/columns block contains two core/column blocks, which each contain various blocks such as core/post-title, core/post-date, core/post-author, and core/post-excerpt.

The structure of the inner blocks creates a layout with flip cards, where each card has a front and backside. The front side of the card contains a featured image, and the back side contains the post title, date, author, and excerpt. The blocks are nested inside each other to create the desired layout and functionality.

If you’re having trouble understanding how to access the block’s attributes, a helpful resource is the block library on GitHub. Alternatively, you can view the block’s attributes by clicking the Code editor option under the Editor toolbar, or by referring to the attributes we registered earlier.

The same applies to all blocks, I found it very helpful when looking for the attributes.

Adding Styles

The finishing touch will be adding our styles, which are the following:

With all the pieces in place, we can now see the results of our custom query loop variation. In the block editor and on the frontend of the site, we should see:

I hope you’ve enjoyed this tutorial and have learned how to create custom query loop variations in the block editor. With these skills, you can give your content a unique look and feel and customize the Query Loop block to meet your needs. Thanks for following along, and I look forward to seeing what you create!


2 thoughts on “Having Fun with Query Loop Block

  1. Great tutorial, a bit difficult for beginners though. I was wondering if this query would be very interesting if could be displayed based on rules. I was trying to display a query loop in a single post page for a specific cpt X, then in the query loop I want to display posts from a cpt Y where it would have a custom field called parentid and the query is filtered where current post id = parentid of the posts in the loop. Would this be possible? Thank you very much.

  2. Hello, Thank you for your feedback on the tutorial. While the current version might not directly support your scenario, Consider using an alternative like the Advanced Query Loop plugin, or a custom solution using filters, and higher-order components (HOCs) to achieve your specific requirement.

    These links can help:

Have a comment?

Your email address will not be published. Required fields are marked *

accessibilityadminaggregationanchorarrow-rightattach-iconbackupsblogbookmarksbuddypresscachingcalendarcaret-downcartunifiedcouponcrediblecredit-cardcustommigrationdesigndevecomfriendsgallerygoodgroupsgrowthhostingideasinternationalizationiphoneloyaltymailmaphealthmessagingArtboard 1migrationsmultiple-sourcesmultisitenewsnotificationsperformancephonepluginprofilesresearcharrowscalablescrapingsecuresecureseosharearrowarrowsourcestreamsupporttwitchunifiedupdatesvaultwebsitewordpress