Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(navigation): allow passing QueryBuilder or QueryBuilderParams in fetchNavigation or <ContentNavigation> #1206

Merged
merged 7 commits into from
Jun 3, 2022
34 changes: 33 additions & 1 deletion docs/content/4.api/1.components/3.content-navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The `<ContentNavigation>`{lang=html} is a renderless component shortening the ac
## Props

- `query`{lang=ts}: A query to be passed to `fetchContentNavigation()`.
- Type: `QueryBuilderParams`{lang=ts}
- Type: `QueryBuilderParams | QueryBuilder`{lang=ts}
- Default: `undefined`{lang=ts}

## Slots
Expand Down Expand Up @@ -43,3 +43,35 @@ The `empty`{lang=ts} slot can be used to display a default content before render
</nav>
</template>
```

## Query

By providing the `query` prop you can customise the content used for navigation.

Here we pass along a `QueryBuilder` instance.

```vue
<script setup>
const catsQuery = queryContent('cats')
/*
// If you'd prefer to pass along raw `QueryBuilderParams`:
const catsQuery = {
where: [
{ _path: /^\/cats/ },
],
}
*/
</script>

<template>
<ContentNavigation v-slot="{ navigation }" :query="catsQuery">
<NuxtLink
v-for="link of navigation"
:key="link._path"
:to="link._path"
>
{{ link.navTitle || link.title }}
</NuxtLink>
</ContentNavigation>
</template>
```
20 changes: 16 additions & 4 deletions src/runtime/components/ContentNavigation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PropType, toRefs, defineComponent, h, useSlots } from 'vue'
import { PropType, toRefs, defineComponent, h, useSlots, computed } from 'vue'
import { hash } from 'ohash'
import type { NavItem, QueryBuilderParams } from '../types'
import { QueryBuilder } from '../types'
import { useAsyncData, fetchContentNavigation } from '#imports'

export default defineComponent({
Expand All @@ -9,7 +10,7 @@ export default defineComponent({
* A query to be passed to `fetchContentNavigation()`.
*/
query: {
type: Object as PropType<QueryBuilderParams>,
type: Object as PropType<QueryBuilderParams | QueryBuilder>,
required: false,
default: undefined
}
Expand All @@ -19,9 +20,20 @@ export default defineComponent({
query
} = toRefs(props)

const queryBuilder = computed(() => {
/*
* We need to extract params from a possible QueryBuilder beforehand
* so we don't end up with a duplicate useAsyncData key.
*/
if (typeof query.value.params === 'function') {
return query.value.params()
}
return query.value
})

const { data, refresh } = await useAsyncData<NavItem[]>(
`content-navigation-${hash(query.value)}`,
() => fetchContentNavigation(query.value)
`content-navigation-${hash(queryBuilder.value)}`,
() => fetchContentNavigation(queryBuilder.value)
)

return {
Expand Down
27 changes: 27 additions & 0 deletions test/fixtures/basic/pages/nav-with-query.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts" setup>
const catsQuery = queryContent('cats')
const numbers = queryContent('numbers')
const dogsQuery = {
where: [
{ _path: /^\/dogs/ }
]
}
</script>

<template>
<ContentNavigation v-for="(q, key) in [dogsQuery, catsQuery, numbers]" v-slot="{ navigation }" :key="key" :query="q">
<div>
{{ navigation }}
<NuxtLink
v-if="navigation"
v-for="link of navigation[0].children"
:key="link._path"
:to="link._path"
style="margin-right: 1rem;"
>
{{ link.navTitle || link.title }}
</NuxtLink>
</div>
<br>
</ContentNavigation>
</template>