The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
DraftComponent

useCwaResource

Bind a display component to its API resource by IRI — fetch, subscribe, and expose to the admin manager.

Low-level composable that fetches resource data and wires into the admin manager. For display components, prefer useCwaComponent — it wraps this composable and adds a plugin system for collections, images, and custom behaviour.

import { toRef } from 'vue'
import type { IriProp } from '#cwa/composables/cwa-resource'
import { useCwaResource } from '#imports'

const props = defineProps<IriProp>()

const { getResource, exposeMeta } = useCwaResource(toRef(props, 'iri'))
const resource = getResource()

defineExpose(exposeMeta)

Signature

useCwaResource(
  iri: Ref<string>,
  options?: {
    styles?: {
      multiple: boolean
      classes: Record<string, string[]>
    }
    name?: string            // for ui/ variant files — must match filename without .vue
    disableManager?: boolean // skip admin manager integration
    autoClass?: boolean      // default true — auto-applies uiClassNames to the root element
  }
)

First argument is a Ref<string> — use toRef(props, 'iri') to convert the iri prop to a ref.

Return values

const { getResource, exposeMeta, $cwa, getCurrentStyleName } = useCwaResource(iriRef)
ReturnTypePurpose
getResource() => Ref<Resource | null | undefined>Call it once in setup to get the resource ref
exposeMetaobjectPass directly to defineExpose
$cwaCwaComposableAccess to auth, resources, UI state
getCurrentStyleName(data) => string | undefinedRead the currently selected style name
uiClassNamesComputedRef<string[] | undefined>The active style classes — auto-applied to the root element by default

const resource = getResource() — call getResource() once to get the reactive resource ref. Never call it in a computed or template — call it once in setup().

resource.value?.data?.title — access your PHP entity fields on .data.

resource.value states:

  • undefined — loading (show skeleton)
  • null — not found
  • object — data available

defineExpose(exposeMeta) is required — without it the admin manager cannot find and select this component.

Style Variants

const { getResource, exposeMeta, getCurrentStyleName } = useCwaResource(toRef(props, 'iri'), {
  styles: {
    multiple: false,
    classes: {
      'Default': [],
      'Filled': ['bg-blue-600 text-white px-6 py-2 rounded-md'],
      'Outlined': ['border border-blue-600 text-blue-600 px-6 py-2 rounded-md'],
    }
  }
})
const resource = getResource()
const currentStyleName = computed(() => {
  if (!resource.value?.data) return undefined
  return getCurrentStyleName(resource.value.data)
})

The style names appear as options in the admin manager. The selected classes are automatically applied to the component's root element — no :class binding needed. To apply them to an inner element instead, pass autoClass: false and bind uiClassNames manually.

UI Variant Files

For a ui/ directory alternative template, the name option sets the label shown in the admin "UI" selector. It does not need to match the filename — it's purely cosmetic. Without it, the selector falls back to the raw component name.

// app/cwa/components/NavigationLink/ui/YouTube.vue
const { getResource, exposeMeta } = useCwaResource(toRef(props, 'iri'), {
  name: 'YouTube'   // optional display label for the admin UI selector
})

See Alternative UI Variants for the full pattern.

Complete Example

<template>
  <h1>{{ resource?.data?.title }}</h1>
</template>

<script setup lang="ts">
import { toRef } from 'vue'
import type { IriProp } from '#cwa/composables/cwa-resource'
import { useCwaResource } from '#imports'

const props = defineProps<IriProp>()
const { getResource, exposeMeta } = useCwaResource(toRef(props, 'iri'))
const resource = getResource()
defineExpose(exposeMeta)
</script>