<CwaComponentGroup />
<CwaComponentGroup> is the primary building block of every CWA page. Place it inside any layout, page template, or component to create a named content region that admins can populate with components in the CMS.
<CwaComponentGroup reference="hero" :location="iri" />
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
reference | string | Yes | — | Name of the component group within this resource. Determines which ComponentGroup entity this region maps to. |
location | string | Yes | — | IRI of the parent resource that owns this group (your layout, page, or component IRI). |
allowed-components | string[] | null | No | null | Collection endpoints of the component types admins may add to this group (e.g. ['/component/hero_banners', '/component/text_blocks']). All CWA component endpoints are prefixed with /component/. When set, the value is synced to the ComponentGroup entity in the API whenever an admin is signed in. null allows all types. |
Basic Usage
Every layout, page template, and component that has editable content regions uses <CwaComponentGroup>. Pass the component's own iri prop as location:
<!-- app/cwa/pages/HomePage.vue -->
<template>
<div>
<CwaComponentGroup reference="hero" :location="iri" />
<CwaComponentGroup reference="features" :location="iri" />
<CwaComponentGroup reference="cta" :location="iri" />
</div>
</template>
<script setup lang="ts">
import type { IriProp } from '@cwa/nuxt/runtime/composables'
defineProps<IriProp>()
</script>
The reference name is how the admin CMS identifies the region. It can be any string — keep it short and descriptive. Multiple groups on the same resource each need a unique reference.
In a Layout
<!-- app/cwa/layouts/PrimaryLayout.vue -->
<template>
<div class="min-h-screen flex flex-col">
<header>
<CwaComponentGroup reference="navigation" :location="iri" />
</header>
<main class="flex-1">
<!-- CWA renders the current page template here -->
<slot />
</main>
<footer>
<CwaComponentGroup reference="footer" :location="iri" />
</footer>
</div>
</template>
<script setup lang="ts">
import type { IriProp } from '@cwa/nuxt/runtime/composables'
defineProps<IriProp>()
</script>
In a Component
Components can themselves contain component groups, enabling nested composition:
<!-- app/cwa/components/TwoColumn/TwoColumn.vue -->
<template>
<div class="grid grid-cols-2 gap-8">
<div>
<CwaComponentGroup reference="left" :location="iri" />
</div>
<div>
<CwaComponentGroup reference="right" :location="iri" />
</div>
</div>
</template>
<script setup lang="ts">
import type { IriProp } from '@cwa/nuxt/runtime/composables'
defineProps<IriProp>()
</script>
How It Works
When <CwaComponentGroup> mounts it:
- Looks up the
ComponentGroupentity for{reference}_{location IRI}in the resource store - Reads the ordered list of
ComponentPositionentities from that group - Renders each
ComponentPosition's component using theuiComponentfield as the Vue component name - In admin edit mode, wraps each component with selection handles and the add-component button
The group reference is stable — it identifies the same region across environments as long as the location IRI is the same.
Allowed Components
The API can restrict which component types are allowed in a specific group. The restriction is enforced in two places:
- Write-side (admin UI) — components not in the allowed list are hidden from the "Add Component" dialog for that group.
- Read-side (rendering) —
ComponentPositionentries whose resolved component type is not inallowedComponentsare omitted from the API response entirely. This means a component that was positioned beforeallowedComponentswas set (or whose type was later removed from the list) will silently not render.
Via the Vue prop — pass collection endpoint paths directly in the template. The module syncs this to the API entity whenever an admin is signed in, creating or updating the group as needed:
<CwaComponentGroup
reference="hero"
:location="iri"
:allowed-components="['/component/hero_banners', '/component/video_blocks']"
/>
Via fixtures — pass an array of PHP FQCNs as the second argument to ->group():
$cwa->layout('primary', 'PrimaryLayout')
->group('hero', [App\Entity\HeroBanner::class, App\Entity\VideoBlock::class]);
Via REST API — send PHP FQCNs in allowedComponents when creating or updating a ComponentGroup. The API normalizes them to collection IRIs automatically:
{
"allowedComponents": [
"App\\Entity\\HeroBanner",
"App\\Entity\\VideoBlock"
]
}
The normalizer converts these FQCNs to their /component/ collection endpoints (e.g. /component/hero_banners) before persisting.
The allowedComponents field is also returned when reading a Layout or Page with embedded component groups.