Collections & Pagination
The Collection built-in component proxies any resource collection endpoint. On the front-end, useCwaCollectionResource unwraps the Hydra response and gives you items, pagination state, and navigation helpers — all URL-bound.
Display Component
<!-- app/cwa/components/BlogList/BlogList.vue -->
<template>
<div>
<div v-if="isLoadingCollection" class="space-y-4">
<div v-for="n in 6" :key="n" class="h-48 bg-gray-100 animate-pulse rounded" />
</div>
<div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<ArticleCard
v-for="item in collectionItems"
:key="item['@id']"
:article="item.data"
:href="resolveResourceLink(item)"
/>
</div>
<div v-if="totalPages > 1" class="flex items-center justify-center gap-4 mt-8">
<button
:disabled="!pageModel || pageModel <= 1"
class="btn"
@click="goToPreviousPage"
>
Previous
</button>
<span class="text-sm text-gray-600">
Page {{ pageModel }} of {{ totalPages }}
</span>
<button
:disabled="pageModel >= totalPages"
class="btn"
@click="goToNextPage"
>
Next
</button>
</div>
</div>
</template>
<script setup lang="ts">
import { toRef } from 'vue'
import type { IriProp } from '#cwa/composables/cwa-resource'
import { useCwaCollectionResource } from '#imports'
import { resolveResourceLink } from '@cwa/nuxt/runtime/utils'
const props = defineProps<IriProp>()
const {
getResource,
exposeMeta,
collectionItems,
isLoadingCollection,
totalPages,
pageModel,
goToNextPage,
goToPreviousPage
} = useCwaCollectionResource(toRef(props, 'iri'))
const resource = getResource()
defineExpose(exposeMeta)
</script>
Return Values
| Return | Type | Description |
|---|---|---|
collectionItems | ComputedRef<Resource[]> | The hydra:member array — each item is a full resource |
isLoadingCollection | ComputedRef<boolean> | true while the proxied collection fetch is in progress |
totalPages | ComputedRef<number> | Computed from hydra:totalItems ÷ perPage |
pageModel | Ref<number> | Current page number — bound to the URL ?page= query param |
goToNextPage | () => void | Increments pageModel |
goToPreviousPage | () => void | Decrements pageModel (min: 1) |
changePage | (page: number) => void | Jump to a specific page |
collectionItems is always an array — never null — so v-for won't error during loading.
Numbered Pagination
Use useCwaCollectionPagination to generate a page number list with ellipsis markers for long ranges:
import { useCwaCollectionPagination } from '#imports'
const { pages } = useCwaCollectionPagination(totalPages, pageModel)
// pages.value → [1, 2, '...', 8, 9, 10] when on page 1 of 10
<nav class="flex gap-1">
<button
v-for="p in pages"
:key="p"
:disabled="p === '...'"
:class="p === pageModel ? 'font-bold' : ''"
@click="typeof p === 'number' && changePage(p)"
>
{{ p }}
</button>
</nav>
Linking to a Resource's Page
resolveResourceLink looks up the Route whose PageData IRI matches the item, and returns the path:
import { resolveResourceLink } from '@cwa/nuxt/runtime/utils'
// In template
:href="resolveResourceLink(item)"
This is how you turn a collection item into a <NuxtLink> without knowing its URL in advance.
User-Controlled Sorting and Filtering
useQueryBoundModel binds any query parameter to the URL, triggering a re-fetch when it changes:
import { useQueryBoundModel } from '#imports'
const sortOrder = useQueryBoundModel('order[createdAt]', 'desc')
// Changing sortOrder.value updates ?order[createdAt]=... in the URL
<select v-model="sortOrder">
<option value="desc">Newest first</option>
<option value="asc">Oldest first</option>
</select>
The collection re-fetches automatically when the URL changes. Default query parameters set in the PHP Collection entity are the baseline; useQueryBoundModel lets users override them.
Admin: Setting Up a Collection
The manager tab (auto-provided by the built-in Collection entity) lets admins:
- Select which resource to list (
resourceIri— searchable dropdown) - Set
perPage— how many items per page - Configure
defaultQueryParameters— default sort and filter values
No custom admin tab file needed for the standard Collection component — it's provided by the bundle.