Navigation Tree
Sometimes you need a navigation so your users know where to go. This recipe will show you how to create a navigation tree for your Shopify store in Nuxt.
<script setup lang="ts">
const props = defineProps<{
handle: string
}>()
const key = computed(() => `menu-${props.handle}`)
const { data: items } = await useAsyncStorefront(key, `#graphql
query GetNavigation($handle: String!, $language: LanguageCode, $country: CountryCode)
@inContext(handle: $handle, language: $language, country: $country) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
`, {
variables: {
handle: props.handle,
language: 'EN',
country: 'US',
},
}, {
transform: data => data.menu?.items?.map(item => ({
label: item.title,
to: item.url,
})) ?? [],
})
</script>
<template>
<UNavigationMenu :items="items" />
</template>
In order to follow this recipe, you need to have a navigation menu set up in your Shopify store. Make sure you have configured the Nuxt Shopify module and have a Shopify store set up.
Obtaining the Menu Data
First, we create a new component components/NavigationTree.vue
.
Here, we use the useAsyncStorefront
composable to fetch the navigation menu from Shopify.
To do this, we use a GraphQL query to get the menu items by their handle (e.g., main-menu
):
query GetNavigation($handle: String!) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
When using this query with the useAsyncStorefront
composable, we pass the handle as a variable:
<script setup lang="ts">
const { data } = await useAsyncStorefront('menu', `#graphql
query GetNavigation($handle: String!) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
`, {
variables: {
handle: 'main-menu',
},
})
</script>
<template>
<pre>{{ data }}</pre>
</template>
The result will be a list of menu items with their titles and URLs.
Transforming the Data
The data
returned from the query is a good starting point, but we want to transform the data into a format that
can be used by a navigation component, in this case the Nuxt UI UNavigationMenu
.
To do so, we can use the transform
option of useAsyncData
, which is built into the useAsyncStorefront
composable:
<script setup lang="ts">
const { data: items } = await useAsyncStorefront('menu', `#graphql
query GetNavigation($handle: String!) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
`, {
variables: {
handle: 'main-menu',
},
}, {
transform: data => data.menu?.items?.map(item => ({
label: item.title,
to: item.url,
})) ?? [],
})
</script>
<template>
<UNavigationMenu :items="items" />
</template>
And that's it! You now have a navigation tree that fetches its data from Shopify.
If you want to use a different menu, just change the handle
variable to the handle of your desired menu in Shopify.
Making the Component Reusable
At this point, it might also make sense to add a handle
prop to the component so you can reuse it for different menus.
We can also translate the menu to a specific language and country by using an @inContext
directive in the GraphQL query:
query GetNavigation($handle: String!, $language: LanguageCode, $country: CountryCode)
@inContext(handle: $handle, language: $language, country: $country) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
When adding all of this together, we get the final component.
You can use this component anywhere in your app, just make sure to pass the correct handle
:
<script setup lang="ts">
const props = defineProps<{
handle: string
}>()
const key = computed(() => `menu-${props.handle}`)
const { data: items } = await useAsyncStorefront(key, `#graphql
query GetNavigation($handle: String!, $language: LanguageCode, $country: CountryCode)
@inContext(handle: $handle, language: $language, country: $country) {
menu(handle: $handle) {
items {
... on MenuItem {
title
url
}
}
}
}
`, {
variables: {
handle: props.handle,
language: 'EN',
country: 'US',
},
}, {
transform: data => data.menu?.items?.map(item => ({
label: item.title,
to: item.url,
})) ?? [],
})
</script>
<template>
<UNavigationMenu :items="items" />
</template>