Table of contents
WordPress API Nav Menu
How to get nav menu items into Nuxt 3 through the WordPress REST API. This can seem difficult at first. But trust me, once you know what you are doing it will all make perfect sense.
Add menu theme support
Check if we can create menus
The first thing we need to do is make sure that we have the ability to create menus in our WordPress backend. Hover over the “Appearances” menu item in the left hand sidebar. A sub menu will appear. If you do not see the “Menus” option in the sub menu, you will need to enable theme support for them. If you do see the “Menus” option skip to the Create a menu part.
Enable theme support for WP menu
To enable theme support for menus, we need to edit the functions.php file in our theme. Open the functions.php file and add the following code:
<?php
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
// other stuff
// add menu support
add_theme_support( 'menus' );
Save your functions.php file. Now hover over the “Appearances” menu item again and you should see the “Menus” option in the submenu!
Create a WordPress menu
We are now at a point where we can create a menu. So click on the “Menus” option. Give your menu a name then click the Create Menu button. It is important that we remember the name of this menu as we are going to use it to reference the menu later. Add some items to the menu and save the menu. I am adding the home and about pages to my menu and naming it ‘top-nav’.
Create WordPress API endpoint for nav menu
We now need to create an API endpoint for our WordPress nav menu. This is so we can retrieve the items from the menu via the WordPress API. Head back to your theme’s functions.php file. Add the following code:
<?php
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
// other stuff
// add menu support
add_theme_support( 'menus' );
// Return formatted top-nav menu
function top_nav_menu() {
$menu = wp_get_nav_menu_items('top-nav');
$result = [];
foreach($menu as $item) {
$my_item = [
'name' => $item->title,
'href' => $item->url
];
$result[] = $my_item;
}
return $result;
}
// add endpoint
add_action( 'rest_api_init', function() {
// top-nav menu
register_rest_route( 'wp/v2', 'top-nav', array(
'methods' => 'GET',
'callback' => 'top_nav_menu',
) );
});
Let’s take a look at the code we just added to our functions.php file.
WP rest_api_init action hook
we can see that we hook into the rest_api_init
action. When the rest_api_init
action runs, it executes the callback function defined within. This callback function then calls the register_rest_route
function which registers a new endpoint in our WordPress API. You will see we pass 3 parameters to the register_rest_route
function:
-
$route_namespace (string)
This is the first URL segment after core prefix. In our case it is ‘wp/v2’.
-
$route (string)
This is the base URL for route. In our case it is ‘top-nav’. This can be named anything you want. But it makes sense to use something related to the previously created nav menu.
-
$args (array)
This is an array of options for our endpoint. In our example we have set the method to ‘GET’ and the callback to ‘top_nav_menu’. This means that when we hit our endpoint we will execute
top_nav_menu()
.
Structure menu items with register_rest_route callback function (top_nav_menu())
We have also created a top_nav_menu
function. This function runs when we hit our endpoint! If we take a look at this function we will see that it fetches our nav menu using wp_get_nav_menu_items
. This is where we pass the name of our nav menu that we created earlier. We then loop over each menu item, adding only the properties that we want to return. We are only interested in the title and url of each menu item. I have assigned these to a ‘name’ and ‘href’ property in an array on each iteration, which are then pushed to a $results
array. Finally the $results
array is returned.
Set Site Address (URL) in WordPress
We now need to set the site address (url). Go to ‘General’ settings in WordPress. We need to set ‘Site Address (URL)’ to the location of our frontend. In this case it will be the location of our Nuxt.js application. This is currently http://localhost:3000 if you are on localhost. Or if not, it will be whatever the address of your frontend is.
If we forget to do this our url’s from the menu items will point to our WordPress backend, which will break everything! Double check if your frontend is http or https. In my case I am using http for localhost:3000 (http://localhost:3000). Make sure you click Save Changes.
Create nav menu component in Nuxt 3
We are nearly there! Now we need to create our nav menu component in our Nuxt 3 application. You can style this how you like, but make sure you have the following code in your component:
<template>
<div>
<a v-for="item in navigation" :key="item.name" :href="item.href" :aria-current="item.href === current ? 'page' : undefined">{{ item.name }}</a>
</div>
</template>
<script setup>
const route = useRoute()
// Replace 'http://localhost:3000' with your frontend location
const current = 'http://localhost:3000' + route.fullPath
// IMPORTANT
// If your frontend is http then use http
// in your useFetch endpoint
// If it is https then use https
// Replace 'http://wp.websitegoblin.com' with your backend location
const { data: navigation, pending, error, refresh } = await useFetch('http://wp.websitegoblin.com/wp-json/wp/v2/top-nav');
</script>
Fetch WordPress menu API data with useFetch()
In our nuxt.js nav component we use the useFetch() nuxt.js function to fetch our WordPress menu items from our custom endpoint. We then loop over the array that is returned and create our nav links using the data from our WordPress menu.
Http / Https gotcha!
If your frontend is using http, you must also fetch data from your endpoint using http. Even if your WordPress Address (URL) is https. For example: I am using https://wp.websitegoblin.com
for my backend (notice it is https). I am using http://localhost:3000
for my frontend (http). This is how I would have my useFetch function:
// Using http eventhough backend is https
const { data: navigation, pending, error, refresh } = await useFetch('http://wp.websitegoblin.com/wp-json/wp/v2/top-nav');
Check you fetch request. If your frontend is HTTP you must make your fetch request to HTTP even if your backend is HTTPS
If you get this wrong your url’s will point to the wrong pages. Basically whatever you use in the endpoint fetch request (http or https) is what will be used in the url’s that are returned from the WordPress API.
So there you have it. That is how you create a nav menu in WordPress and pull it into Nuxt 3 using the WordPress REST API!
I have videos too!
If you found this post helpful, please consider subscribing to the @codingoblin YouTube channel 😀