CWA 2.0 is in alpha: try it, build with it, give feedback. APIs can still change between releases; see Releases.
Form

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)

Signature

useCwaForm(iri: Ref<string | undefined>)

Parameters

ParameterTypeDescription
iriRef<string | undefined>IRI of the Form component resource

Return Values

PropertyTypeDescription
submit() => Promise<void>Submit the form — see below
submittingRef<boolean>true while the submit request is in-flight
successRef<boolean>true after a successful submission
formErrorsComputedRef<string[]>Root form-level error messages from the API response
unregisteredFieldErrorsComputedRef<string[]>Errors from fields the API returned but no useCwaFormInput is bound to — prevents silent error loss

submit()

Calling submit():

  1. Resets success to false
  2. Reads the current field values for this form from the shared store (populated by each useCwaFormInput field)
  3. Reads action and method from the root form vars in the API response
  4. POSTs or PATCHes to the submit endpoint with all field values using Symfony full_name keys (e.g. contact_form[name])
  5. On success — sets success = true and clears submitAttempted (hides errors in all fields)
  6. On failure (422) — sets submitAttempted = true (triggers displayErrors in every useCwaFormInput for this form); formErrors and unregisteredFieldErrors update automatically from the store

submitting is true for the duration of the request.

Error Display Contract

Three error sources cover every possible API error:

SourceWhat it containsWhere to render
useCwaFormInput.errors, gated by displayErrorsErrors for that specific registered fieldNext to the field
formErrorsRoot-level form messages (e.g. CSRF, global validation)At the top of the form
unregisteredFieldErrorsErrors for form fields the API returned but no useCwaFormInput boundNext to formErrors

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">
import type { IriProp } from '#cwa/composables/cwa-resource'

const props = defineProps<IriProp>()
const { exposeMeta } = useCwaComponent(props)
defineExpose(exposeMeta)

const iriRef = toRef(props, 'iri')
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

  • formErrors reads the root form's vars.errors from the store — it updates automatically on 422
  • unregisteredFieldErrors iterates all form field views in the store, skipping the root and any key registered via useCwaFormInput; useful as a fallback block
  • The submitAttempted flag is shared state in $cwa.forms keyed by IRI — no provide/inject required; all useCwaFormInput instances for the same form IRI respond to it automatically
  • See the Forms guide for full field-type examples