Queries
Overview
A query is a request to the Storyblok API to retrieve data. For this scenario we have made <SbQuery>
which act as a wrapper for multiple requests.
Use-Cases
<SbQuery>
is a powerful component for showing a list of data from Storyblok API.
- Use it as wrapper for your custom lists and grid designs in your website (Team members, products, portfolio items)
- Archive pages for news or blog items
- Filter and sort the data
- Make items searchable inside SbQuery
Simple Queries
a) Slot approach
- Retrieve multiple
posts
from theposts
folder in storyblok. - Use default slot with scoped
story
object.
<SbQuery path="posts">
<template #default="story">
<li>
<nuxt-link :to="story.full_slug">
<h3>{{ story.content.title }}</h3>
<p>{{ story.content.excerpt }}...</p>
</nuxt-link>
<li>
</template>
</SbQuery>
Create reusable components:
<SbQuery path="posts">
<template #default="story">
<SingleArticle v-bind="story" />
</template>
</SbQuery>
<template>
<li>
<nuxt-link :to="story.full_slug">
<h3>{{ story.content.title }}</h3>
<p>{{ story.content.excerpt }}...</p>
</nuxt-link>
<li>
</template>
<script>
export default {
props: {
story: {
type: Object,
default: () => ({})
}
}
}
</script>
b) Content type approach
With <SbQuery>
we are retriving a list of stories based on a content type
. You can create a separete vue component with the name of this content type (e.g. Job.vue
). <SbQuery>
will look for the component with same name as the content type and includes it.
Retrieve multiple posts with content-type Post.
<SbQuery path="posts" />
<template>
<li>
<nuxt-link :to="story.full_slug">
{{ story.content.title }}
</nuxt-link>
</li>
</template>
<script>
export default {
props: {
blok: {
type: Object,
default: () => ({})
}
}
}
</script>
parent -> child
hierachy than the Content type approach. It always depends on use case.
Pagination
For longer lists you might want to split the retrieved content into multiple pages. As of now we can choose between infinite
, numeric
and none
pagination types.
Example for infinite pagination with a Load more (i18n ready) button.
<SbQuery path="portfolio" pagination-type="infinite" />
Example for a numeric pagination example
<SbQuery path="portfolio" pagination-type="numeric" />
Complete custom pagination template.
<SbQuery path="portfolio">
<template #pagination="{loadMore, currentPage, total}">
{{ currentPage }} / {{ total }}
<button @click="loadMore">
LOAD MORE
</button>
</template>
</SbQuery>
Full example
<SbQuery :options="{per_page: 1}" path="jobs" :filter-client-only="false">
<template #default="story">
<JobItem :title="story.content.title" :salary="story.content.salary" :link="story.full_slug" />
</template>
<template #pagination="{loadMore, currentPage, total}">
{{ currentPage }} / {{ total }}
<button @click="loadMore">
LOAD MORE
</button>
</template>
</SbQuery>
Filter and sort strategy
This affects
- Pagination
- Filters
- Sorting
We offer two strategies how you can handle pagination logic. This is controlled with the filterClientOnly
prop.
Client only
filterClientOnly: true
: Auto fetch 100 (max. from Storyblok) stories and do all logic on clientside (without refetching from server). This is recommend for small data where server requests not make much sense.
Advantages:
- Very fast. No additional server requests needed.
Disadvantages:
- Limited to max. 100 posts at once.
<SbQuery path="jobs" :posts-per-page-client-only="25" :filter-client-only="true" />
Server fetching
filterClientOnly: false
: Recommend for bigger amount of stories. With this approach you fetch piece by piece from server for each page. Filter and sort is also handled by server requests via Storybok API.
<SbQuery path="jobs" :filter-client-only="false" />
Advantages:
- Always consistent since we're fetching from server.
- Support unlimited data
> 100 entries
Disadvantages:
-
Limited to max. 100 posts at once.
-
For every filter, sort process a request to the server will be made.
-
Not recommend for small lists.
Render hooks
afterFetchCollection
Sometimes you need to manipulate
data from outside and use this updated data in the rendered template. You can hook into afterFetchCollection
hook and mutate the given Storyblok collection.
For example if you want to remove expired
jobs on client before render:
<template>
<ul>
<SbQuery path="jobs" @afterFetchCollection="removeExpiredJobs">
<template #default="item">
<JobItem :title="item.content.title" :salary="item.content.salary" :link="item.full_slug" />
</template>
</SbQuery>
</ul>
</template>
<script>
export default {
props: {
bloks: {
type: Object,
default: () => ({})
}
},
methods: {
removeExpiredJobs(collection) {
return this.collection.filter((job) => {
if (job.content.expired === false) {
return job
}
})
}
}
}
</script>
Component Api
<SbQuery>
Props
Prop | Default | Type | Description |
`options` |
{
sort_by: 'created_at:desc'
} |
`Object`
|
Any options from Storyblok API Documentation
|
`path` |
`` |
`String`
|
Filter by
full_slug to retrieve data from a specific folder. Uses `starts_with` option.
|
`paginationType` |
`infinite` |
`string`
|
Choose a pagination type.
infinite , numeric , none
|
`filterQuery` |
`{}` |
`Object`
|
Add a custom caption text
|
`disableFetch` |
`false` |
`Boolean`
|
You can disable remote fetching. Use this in combination with dataSource
|
`dataSource`
|
`false` |
`Boolean`
|
SbQuery is basically designed to fetch remote data. But you can fill it with a custom data array and use it other features like pagination e.g.
|
`postsPerPageClientOnly`
|
`12` |
`Number`
|
How many items should be shown on one page. Use `-1` to show unlimited items. This is a client only solution. If you want to limit posts on server fetching use `options.per_page` prop.
|
`filterClientOnly`
|
`true` |
`Boolean`
|
See [Filter and sort strategy](/components/queries#filter-and-sort-strategy)
|