wp-lemon Docs

Block controller

Block controller

The block controller is where you'll probably spend most time while developing a custom block. This is where you process any dynamic data and control how your block behaves based on input from the editor. The idea is to put all of our logic in here, so that when you're working in the view layer, you only have to focus on creating a beautiful front end.

Anatomy of a block controller

In the block controller you will find 2 methods you can use to expand your block:

  • block_context()
  • add_fields()

The block_context() function is used to query the data from the database and add it to the block context.

Block content

There are two main ways to add content to your block.

  • InnerBlocks
  • ACF fields

We prefer InnerBlocks over ACF fields because it uses native WordPress functionality. The reason you might want to use ACF fields is for repeater fields like slides or testimonials. Below we'll show you how to use both methods.

InnerBlocks

InnerBlocks are blocks within blocks. This way you can create complex blocks with multiple child blocks. This gives the user a lot of control over the layout of the block. To learn how to use InnerBlocks, take a look at the InnerBlocks documentation.

Adding ACF fields to the block

You can add any type of ACF field to the block. To find out all the possibilities take a look at the ACF documentation. Here you'll find all the different field types and how to use them. Below is a simple example of what your add_fields() function could look like.

public function add_fields(): object
{
$this->registered_fields
->addRepeater(
'slides',
[
'layout' => 'block',
'min' => 1,
'max' => 4,
]
)
->addImage('image', [
'label' => 'Image',
'return_format' => 'id',
'preview_size' => 'medium',
])
->addText('caption', [
'label' => 'Bijschrift',
])
->endRepeater();
return $this->registered_fields;
}

To learn how to use these fields in your block view, take a look at the block view documentation.

Extending the block context

Every block is different but we will give some common examples on how to expand your block.

Block that displays an x amount of (custom)posts

Take a look at the news-recent.php block in the parent theme. You will find a method block_context(). When going through these lines you will find several notable things.

1public function block_context($context): array
2{
3 $amount = get_field('amount') ? get_field('amount') : 3;
4 $items = latest_items_query('news', $amount);
5 $context['items'] = $items;
6 $context['card_type'] = 'news';
7 $context['holder_classes'] = 'col-12 col-md-6 col-lg-4';
8 $message = __("You haven't added any news yet, so this block will be empty.", "wp-lemon");
9
10 if ($items->found_posts == 0) {
11 self::add_notification($message, 'warning');
12 }
13
14 return $context;
15}
  • wp-lemon comes with a set of predefined queries. Here we use latest_items_query() to get the latest posts of a specific posttype
  • We have a card_type variable that defines what card type will be loaded.
  • We have a add_notification method that will setup a notification inside the block when previewed in the backend.

Block that displays a post archive with load more button

Take a look at the news-overview.php block in the parent theme. You will again find a method block_context() that will query the data from the database and add it to the block context.

1public function block_context($context): array
2{
3 $items = archive_query('news', 6); // query the news posttype
4 $context['items'] = $items;
5 $context['nav'] = true; // show nav
6 $context['count'] = get_total_posts('news', count($items)); // get a count array that feeds information to the postholder.
7 $context['post_type'] = 'news'; // sets post type for the ajax calls.
8 $context['card_type'] = 'news'; // sets the twig partial to render the actual posts in the loop.
9 $context['holder_classes'] = 'col-12 col-md-6 col-lg-4'; // holder classes around the cards in the loop.
10
11 if (isset($this->fields['show_filter']) && $this->fields['show_filter'] == true) {
12 $context['show_filter'] = true;
13 $context['terms'] = get_terms('category', array('hide_empty' => true));
14 }
15
16 // add notification when no posts are found.
17 if ($items->found_posts == 0) {
18 self::add_notification(__('You haven\'t added any news yet, so this block will be empty.', 'wp-lemon'), 'warning');
19 }
20
21 return $context;
22}

The linked blocks/news-overview.twig file will include components/archive-loop.twig that will display the initial posts and setup everything for receiving new posts via an ajax call.

When reusing above code make sure to:

  • set the post type correctly
  • create a new card twig file
  • include the components/archive-loop.twig inside your twig file that is linked to your block.
  • Update the notice to inform the administrator/editors of the website when no posts are found of the posttype you want to query.
  • include the right functions in your file like so
1namespace WP_Lemon\Child\Blocks;
2
3use HighGround\Bulldozer\BlockRenderer;
4
5++ use function WP_Lemon\API\archive_query;
6++ use function WP_Lemon\API\get_total_posts;

Block with custom assets

You might want to add a specific asset to the blocks context as it is only used by this specific block. You can use the asset() helper function for that.

1public function block_context($context): array
2{
3 // Check if shape exists.
4 if(true == asset('images/banner.png')->exists()){
5 // get URL to image/shape
6 $context['banner_uri'] = asset('images/banner.png')->uri();
7 }
8
9 // get contents of the svg to use directly in to your block.
10 $context['sphere'] = asset('images/sphere.svg')->contents();
11
12 return $context;
13}

Block that needs conditional modifier classes

You might want to add conditional classes based on a field setting. This is where $this->add_modifier_class('yourmodifier'); comes in. This method adds a BEM modifier class to your block. An example:

1public function block_context($context): array
2{
3
4 if (isset($this->fields['show_pagination']) && true == $this->fields['show_pagination']) {
5 $context['show_pagination'] = true;
6 $this->add_modifier_class('has-pagination');
7 }
8
9 return $context;
10}

will result in

1<div class="acf-block slider slider--has-pagination" id="block_5f8ffdc0349e1">
2...
3</div>

Wp-lemon queries

When you want to use post objects within your custom block you can use the following queries in your block context:

FunctionDescription
latest_items_queryRetrieves the latest posts of a specific type, optionally filtered by taxonomy and terms.
other_items_queryFetches posts of a specific type, excluding a given post, optionally filtered by taxonomy and terms.
specific_items_queryRetrieves specific posts by their IDs and type.
archive_queryFetches a set of posts of a specific type for archive display, supporting pagination.
get_total_postsCalculates the total number of posts available for an AJAX "load more" functionality.
adjacent_post_infoGets information about the next or previous post, or returns the first/last post if unavailable.
next_post_infoReturns information about the next post or the first post if no next post exists.
previous_post_infoReturns information about the previous post or the last post if no previous post exists.
taxonomy_post_collectionRetrieves a collection of posts organized by category, based on a taxonomy and post type.
Edit this page on GitHub