Skip to content

Vue Form Adapter

If you use Vue, this package now ships a small adapter layer as a separate subpath export:

javascript
import { useSchemaForm, useSchemaField } from 'json-rest-schema/vue'

That split is intentional.

  • json-rest-schema/vue handles schema-aware form orchestration
  • the core schema engine stays framework-agnostic

Just as important: the adapter does not import Vue internally.

They work with:

  • plain objects
  • Vue reactive proxies
  • Vue refs such as ref({ ... })

That keeps the published package small and avoids turning Vue into a hard dependency of the core runtime.

Basic Vue usage

Use useSchemaForm() when you already own the form values in Vue state.

javascript
import { reactive } from 'vue'
import { createSchema } from 'json-rest-schema'
import { useSchemaForm } from 'json-rest-schema/vue'

const profileSchema = createSchema({
  name: { type: 'string', required: true, minLength: 3 },
  role: { type: 'string', defaultTo: 'guest' }
})

const values = reactive({
  name: ''
})

const form = useSchemaForm(profileSchema, {
  values
})

If you want Vue to react to adapter-managed error or result updates, pass Vue-owned containers such as ref({}), reactive({}), or ref(null):

javascript
import { reactive, ref } from 'vue'

const values = reactive({
  name: ''
})

const errors = ref({})
const lastResult = ref(null)

const form = useSchemaForm(profileSchema, {
  values,
  errors,
  lastResult
})

That keeps reactivity in the Vue app instead of hiding framework state inside the schema library.

Important behavior:

  • full-form validation defaults to create semantics
  • form.validate() returns the usual { validatedObject, errors }
  • form.errors stays in the library's flat dotted-path format
  • form.nestedErrors gives you the nested object/array form if your Vue layer prefers it

Running a full validation:

javascript
const result = form.validate()

If values is:

javascript
{
  name: '  Alex  '
}

then result will be:

javascript
{
  validatedObject: {
    name: 'Alex',
    role: 'guest'
  },
  errors: {}
}

That is the same contract as the core schema engine. The Vue adapter does not invent a second validation format.

Field-level validation in Vue

For blur validation, wizard steps, or one-field re-validation, use the path-aware helpers.

javascript
const fieldResult = form.validateField('name')
const stepResult = form.validateFields(['name', 'role'])

This matters because the adapter validates only the selected paths.

That means:

  • validating name does not suddenly produce email or password errors
  • nested paths such as workspace.slug work the same way as they do in the core APIs
  • bracket paths such as roles[0].label are accepted too

If you want a path-focused helper object, use useSchemaField():

javascript
const nameField = useSchemaField(form, 'name')

It gives you:

  • nameField.value
  • nameField.error
  • nameField.hasError
  • nameField.message
  • nameField.messages
  • nameField.validate()
  • nameField.clearError()

Example:

javascript
nameField.validate()
console.log(nameField.messages)

Submit normalization in Vue

The clean submit path is:

javascript
const submitProfile = form.submit((validatedObject) => {
  return api.saveProfile(validatedObject)
})

submit() always validates first.

If validation fails:

  • the handler is not called
  • the returned value is the validation result
  • form.errors is updated

If validation succeeds:

  • the handler receives the normalized validatedObject
  • defaults and casts are already applied

This keeps the same intended split as the rest of the library:

  • raw values while the user is typing
  • normalized values at the submit boundary

Edit forms and custom operations in Vue

If the form is editing an existing resource, choose a different operation explicitly:

javascript
const form = useSchemaForm(profileSchema, {
  values,
  operation: 'patch'
})

You can also use a custom schema operation:

javascript
const form = useSchemaForm(profileSchema, {
  values,
  operation: 'upsert'
})

The adapter routes everything back through the schema operation registry, so custom operations behave the same way here as they do in the core runtime.

If you render those forms with Vuetify, use the separate bridge below. It stays thin on purpose and translates the Vue adapter's existing validation results into Vuetify-friendly props and rule callbacks.

GPL-3.0-only