DEV Community

Shriji
Shriji

Posted on • Edited on

Headless WordPress + Sapper Navigation with Menus (Part 4)

WordPress API doesn't have an endpoint for obtaining menu and menu items this requires WP-REST-API V2 Menus Plugin and after installing it unlocks new routes

  • /menus/v1/menus list of every registered menu.
  • /menus/v1/menus/ data for a specific menu.
  • /menus/v1/locations list of every registered menu location in your theme.
  • /menus/v1/locations/ data for a specific menu location.

Testing plugin

In the browser https://YOUR-DOMAIN/wp-json/menus/v1/menus hitting this should give you the menus if not check if the plugin is activated and make sure that you have created a menu with items

[{
    "term_id": 2,
    "name": "Main Menu",
    "slug": "main-menu",
    "term_group": 0,
    "term_taxonomy_id": 2,
    "taxonomy": "nav_menu",
    "description": "",
    "parent": 0,
    "count": 2,
    "filter": "raw"
}]
Enter fullscreen mode Exit fullscreen mode

https://YOUR-DOMAIN/wp-json/menus/v1/menus/main-menu will give all the items in the menu so we will be interested in that and populate the respective slugs.

Accessing page via menu

In the previous post (IMHO a better solution) but if you tend to have too many pages then menu would work better I guess🤷.

Just like how we were able to pass props via /pages API a similar method can be used for Menu API but remember this code is not designed for custom links which don't have the slug property and my suggestion for this to fully use custom links and target url instead of slug.

In your _layout.svelte

<script context="module">
    //uses menu endpoint
    export async function preload() {
        const res = await this.fetch(`https://YOUR-DOMAIN/wp-json/wp/v2/menus/v1/menus/main-menu`)
        const data = await res.json()
        return {
            data
        }
    }
</script>

<script>
    export let data;
    import Nav from '../components/Nav.svelte';
    export let segment;
    export let pageData = [];
       //data.items are an array of menu items.
    data.items.map(e=>{
        let obj = 
        {
            id:e.ID,
            slug:e.slug
        }

        pageData.push(obj)
    })

</script>
Enter fullscreen mode Exit fullscreen mode

On the Nav.svelte has no change from the previous post

<script>
    export let segment;
    export let pageData;
</script>
Enter fullscreen mode Exit fullscreen mode

To the list of existing menus add this snippet that compares and adds the active class

{#each pageData as page }
    <li><a rel=prefetch aria-current="{segment === page.slug ? 'page' : undefined}" href="{page.slug}">{page.slug}</a>
    </li>
{/each}
Enter fullscreen mode Exit fullscreen mode

Next part in the series would be setting up Sapper to be SEO ready for all the pages.

Top comments (0)