This post is baed on code share by deyril_support on https://forum.bricksbuilder.io/t/solved-custom-query-for-nav-menus/26250/4.
In this article, we’ll explore how to create a custom query type for WordPress menu items using the Bricks Builder. This is a powerful way to integrate dynamic navigation menus into your Bricks templates. We will break down the functionality piece by piece, walking you through custom filters and functions to manage menu items effectively.
1. Registering a Custom Query Type for Menu Items
The first thing we need to do is register a new query type specifically for menu items. This allows us to make selections from WordPress menus directly in the Bricks interface.
// Register a custom query type for menu items
add_filter('bricks/setup/control_options', function($control_options) {
$control_options['queryTypes']['menu_items'] = esc_html__('Menu Items', 'bricks-child');
return $control_options;
});2. Adding Custom Controls for Selecting Menus
Next, we add custom controls to allow the user to select the WordPress menu they want to display.
add_filter('bricks/elements/container/controls', 'add_menu_controls', 40);
add_filter('bricks/elements/block/controls', 'add_menu_controls', 40);
add_filter('bricks/elements/div/controls', 'add_menu_controls', 40);
function add_menu_controls($controls) {
$menus = get_terms('nav_menu', ['hide_empty' => true]);
$menu_options = [];
if (!empty($menus) && !is_wp_error($menus)) {
foreach ($menus as $menu) {
$menu_options[$menu->slug] = $menu->name;
}
}
$newControls['menuNameOrId'] = [
'tab' => 'content',
'label' => esc_html__('Select Menu', 'bricks-child'),
'type' => 'select',
'options' => $menu_options,
'placeholder' => esc_html__('Select a menu...', 'bricks-child'),
'required' => [
['query.objectType', '=', 'menu_items'],
['hasLoop', '!=', false],
['isSubmenu', '!=', true]
],
];
$newControls['isSubmenu'] = [
'tab' => 'content',
'label' => esc_html__('Is it for submenu?', 'bricks-child'),
'type' => 'checkbox',
'required' => [
['query.objectType', '=', 'menu_items'],
],
'default' => false,
];
$query_key_index = absint(array_search('query', array_keys($controls)));
$new_controls = array_slice($controls, 0, $query_key_index + 1, true) + $newControls + array_slice($controls, $query_key_index + 1, null, true);
return $new_controls;
}
3. Executing the Custom Query to Fetch Menu Items
Once we have the controls in place, we need to execute the query to actually fetch the menu items. This is done using the bricks/query/run filter.
add_filter('bricks/query/run', function($results, $query_obj) {
if ($query_obj->object_type !== 'menu_items') {
return $results;
}
$settings = $query_obj->settings;
if (!$settings['hasLoop']) {
return [];
}
$menu_id = $settings['menuNameOrId'] ?? '';
$is_submenu = $settings['isSubmenu'] ?? false;
static $stored_menu_id = null;
if (!$is_submenu) {
$stored_menu_id = $menu_id;
$menu_items = wp_get_nav_menu_items($menu_id);
foreach ($menu_items as $item) {
if ($item->menu_item_parent == 0) {
$results[] = $item;
}
}
} else {
if ($stored_menu_id) {
$menu_items = wp_get_nav_menu_items($stored_menu_id);
$parent_query_id = get_query_id(1);
$parent_item = \Bricks\Query::get_loop_object($parent_query_id);
if ($parent_item) {
$parent_id = $parent_item->ID;
foreach ($menu_items as $item) {
if ($item->menu_item_parent == $parent_id) {
$results[] = $item;
}
}
}
}
}
return $results;
}, 10, 2);
4. Mapping the Menu Item Object to the Loop
To display each menu item’s properties in the loop, we map the menu item object to the current loop object using the bricks/query/loop_object filter.
add_filter('bricks/query/loop_object', function($loop_object, $loop_key, $query_obj) {
if ($query_obj->object_type !== 'menu_items') {
return $loop_object;
}
if (isset($query_obj->results[$loop_key])) {
$loop_object = $query_obj->results[$loop_key];
$meta_data = get_post_meta($loop_object->ID);
foreach ($meta_data as $key => $value) {
if (strpos($key, '_') !== 0) {
$acf_value = get_field($key, $loop_object->ID);
if ($acf_value) {
$loop_object->$key = $acf_value;
}
}
if (is_array($value) && count($value) === 1) {
$value = $value[0];
}
if (!isset($loop_object->$key)) {
$loop_object->$key = $value;
}
}
}
return $loop_object;
}, 10, 3);
5. Adding Custom Render Attributes for Menu Items
To style and identify each menu item, we can use bricks/element/render_attributes to add custom attributes and classes.
6. Fetching Menu Item Data
Lastly, we define a helper function to fetch specific data (title, URL, etc.) from the current looped menu item.
The finally you can display the value of menu nav item data such as title, url bu using this code below:
echo:get_menu_item_data('title')
echo:get_menu_item_data('url')By registering a custom query type and adding custom controls and attributes, we’ve built a robust method for managing and displaying dynamic WordPress menus within Bricks Builder. The solution integrates menus seamlessly into the design process, allowing for complex layouts such as nested submenus and custom styling for menu items.

