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.
Component
useCwaForm
Handle form submission, track in-flight state, and read form-level errors from a CWA Form component resource.
useCwaForm manages the submission lifecycle for a Form component. It reads the current field values collected by useCwaFormInput, submits them to the API, and tracks success and error state reactively.
const { submit, submitting, success, formErrors, unregisteredFieldErrors } = useCwaForm(iri)
Parameters
| Parameter | Type | Description |
|---|---|---|
iri | Ref<string | undefined> | IRI of the Form component resource |
Return value
| Property | Type | Description |
|---|---|---|
submit | () => Promise<void> | Submit the form — see below |
submitting | Ref<boolean> | true while the submit request is in-flight |
success | Ref<boolean> | true after a successful submission |
formErrors | ComputedRef<string[]> | Root form-level error messages from the API response |
unregisteredFieldErrors | ComputedRef<string[]> | Errors from fields the API returned but no useCwaFormInput is bound to — prevents silent error loss |
submit()
Calling submit():
- Reads the current field values for this form from the shared store (populated by each
useCwaFormInputfield) - Reads
actionandmethodfrom the root form vars in the API response - POSTs or PATCHes to the submit endpoint with all field values using Symfony
full_namekeys (e.g.contact_form[name]) - On success — sets
success = trueand clearssubmitAttempted(hides errors in all fields) - On failure (422) — sets
submitAttempted = true(triggersdisplayErrorsin everyuseCwaFormInputfor this form);formErrorsandunregisteredFieldErrorsupdate automatically from the store
submitting is true for the duration of the request.
Error display contract
Three error sources cover every possible API error:
| Source | What it contains |
|---|---|
useCwaFormInput.displayErrors / errors | Errors for that specific registered field |
formErrors | Root-level form messages (e.g. CSRF, global validation) |
unregisteredFieldErrors | Errors for form fields the API returned but no useCwaFormInput bound |
Always render unregisteredFieldErrors alongside formErrors so API errors are never silently swallowed — the composable already excludes fields that are registered, so there is no duplication.
Example
<script setup lang="ts">
const props = defineProps<{ iri: string }>()
const iriRef = toRef(props, 'iri')
const { resource } = useCwaResource(props)
const { submit, submitting, success, formErrors, unregisteredFieldErrors } = useCwaForm(iriRef)
</script>
<template>
<form @submit.prevent="submit">
<!-- fields rendered by child components using useCwaFormInput -->
<p v-for="error in formErrors" :key="error" class="text-red-500">{{ error }}</p>
<p v-for="error in unregisteredFieldErrors" :key="error" class="text-orange-500">{{ error }}</p>
<button type="submit" :disabled="submitting">
{{ submitting ? 'Sending…' : 'Submit' }}
</button>
<p v-if="success">Thank you — your message has been sent.</p>
</form>
</template>
Notes
formErrorsreads the root form'svars.errorsfrom the store — it updates automatically on 422unregisteredFieldErrorsiterates all form field views in the store, skipping the root and any key registered viauseCwaFormInput; useful as a fallback block- The
submitAttemptedflag is shared state in$cwa.formskeyed by IRI — noprovide/injectrequired; alluseCwaFormInputinstances for the same form IRI respond to it automatically - See the Forms guide for full field-type examples