Events grouped by Event Date custom field in Bricks

This Pro tutorial for Bricks users provides the steps to output posts of an event custom post type dynamically grouped by the value of their event_date, a date-type custom field (tested with ACF, should also work with other custom field plugins).

Sample data:

  • Event 1: 7 Jul 2020
  • Event 2: 30 Oct 2018
  • Event 3: 14 Dec 2021
  • Event 4: 1 Apr 2020
  • Event 5: 22 Jan 2030
  • Event 6 (no event date)

Output after implementing the tutorial:

This is similar to the Events Grouped by Event Year tutorial, but unlike the earlier one, here we use Bricks elements for the year headings, post title links, etc.

This is a great example to study and understand how to build custom nested query loops in Bricks visually.

Here’s the strategy:

  • Add a new “Event Years” query type.
  • Define a custom function in which we loop through the events whilst ensuring that only the events with non-empty event date are considered and in descending order of event date post meta. This function will be set to return an array of 2 items. The 1st one is an array of all unique years. The 2nd one is an array of years mapped to the corresponding post IDs.
  • In Bricks, create two query loops, one inside another.
  • Set the query type of the outer loop to the above function’s 1st item, i.e., the array of unique years.
  • For the inner loop, enable PHP query editor and set its post__in parameter to the above custom function’s 2nd item with its array key set to the year from the outer loop.

Step 1

Create event CPT and an associated event_date custom field.

There is no need to set the Return Format to Ymd.

Edit event posts and set dates for each.

We shall only fetch the events for which the event date is not empty.

Step 2

Add the following in child theme‘s functions.php or a code snippets plugin:

<?php 

// Add new "Event Years" query loop type option in the dropdown.
add_filter( 'bricks/setup/control_options', function( $control_options ): array {
	$control_options['queryTypes']['event_years'] = esc_html__( 'Event Years' );

	return $control_options;
} );

// Run new query if option selected.
add_filter( 'bricks/query/run', function( $results, $query_obj ): array {
	if ( $query_obj->object_type !== 'event_years' ) {
		return $results;
	}

	// if option is selected, run our new query
	if ( $query_obj->object_type === 'event_years' ) {
		$results = bl_get_event_year_data()[0];
	}

	return $results;
}, 10, 2 );

// Form an array of event years data and return it.
function bl_get_event_year_data(): array {
	// array to store events' years
	$years = [];

	// array to store years => post IDs
	$year_post_ids = [];

	// get events for which event_date is not empty
	$posts = get_posts( [
		'post_type' => 'event',

		'posts_per_page' => 100, // set this to a large enough number
		
		'meta_key' => 'event_date',
		'orderby' => 'meta_value_num',
		'order' => 'DESC',

		'meta_query' => [
			[
				'key' => 'event_date',
				'compare' => 'EXISTS',
				'type' => 'DATE',
			],
			[
				'key' => 'event_date',
				'value' => '',
				'compare' => '!=',
			],
		],
	] );

	// if no events with dates, return empty arrays
	if ( empty( $posts ) ) {
		return [ $years, $year_post_ids ];
	}

	// loop through events and populate the arrays
	foreach ( $posts as $post ) {
		$event_date = get_post_meta( $post->ID, 'event_date', true );

		$year = wp_date( 'Y', strtotime( $event_date ) );

		$years[] = $year;
		$year_post_ids[ $year ][] = $post->ID;
	}

	// sort years in descending order
	// ksort( $years );

	return [ array_unique( $years ), $year_post_ids ];
}

// Function to get the event of the current looping query.
function bl_get_event_year(): string {
	$looping_query_id = BricksQuery::is_any_looping();
	
	if ( $looping_query_id && BricksQuery::get_query_object_type( $looping_query_id ) === 'event_years' ) {
		return BricksQuery::get_loop_object( $looping_query_id );
	}
	
	// return current year in 4 digit format - this is only a fallback and won't be the one that's output
	return date( 'Y' );
}

Note: If code is being added at the end of child theme’s functions.php, do not include the opening PHP tag.

If you are using a code snippets plugin, here’s a title suggestion: Event Years Query Type.

Step 3

Edit a Page where you would like to display the events organized by their years with Bricks.

Copy and paste this Section’s JSON.

Outer query loop:

Heading text:

Inner query loop:

Ensure that eschfz is the Bricks ID of the parent query loop.

Basic Text:

References

https://brickslabs.com/adding-any-custom-wp_query-loop-to-bricks-query-loop/

https://brickslabs.com/parent-query-loop-object-traversing-nested-query-loops-up-in-bricks/

https://www.advancedcustomfields.com/resources/date-picker/

https://support.advancedcustomfields.com/forums/topic/how-to-order-by-date-field/#post-127532