Developer guide

Configuration

The UserConfig object controls validation behavior, interface translations, and every generated CSS class. Pass the same object to the config prop in Vue, Nuxt, React, and Next.js, or to the JavaScript constructor.

Type and structure

interface UserConfig {
  actions: Actions
  translations: Translations
  classNames: UserClassNames
}
PropertyPurpose
actionsControls validation feedback and error navigation.
translationsContains one UI translation object per language key.
classNamesMaps semantic renderer elements and states to CSS classes.
Configuration is merged at the top level

The renderer uses a shallow merge. Supplying actions, translations, or classNames replaces that entire nested default object. Always provide the complete nested object you replace; missing nested keys are not inherited automatically.

Actions

PropertyDefaultBehavior
showOnlyFirstErrorPerInputtrueShow only the first validation message for each invalid field.
showListWithAllFormErrorstrueReserved configuration key. The current renderers do not yet render a separate form-level error summary.
scrollToFirstErrortrueReserved configuration key. The current renderers do not yet scroll automatically after submission.
validateOnBlurtrueValidate a field when the user leaves or commits the control.

Translations

The component's language prop selects a key from config.translations. A translation contains the optional-field label, twelve month names, seven day labels, and the password-toggle labels.

const translations = {
  nl: {
    optional: 'Optioneel',
    months: [
      'Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
      'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'
    ],
    days: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    showPassword: 'Toon wachtwoord',
    hidePassword: 'Verberg wachtwoord'
  }
}

// Select this translation with language="nl".
Calendar array lengths

Keep exactly twelve entries in months and seven entries in days, starting with Sunday, because calendar controls use their array positions.

Complete default configuration

Copy this object when you need a fully custom configuration. Change values while preserving the complete shape required by UserConfig.

import type { UserConfig } from '@jcees-forms/types/interfaces/user-config'

const classNamePrefix = 'jc-'

export const config: UserConfig = {
  actions: {
    showOnlyFirstErrorPerInput: true,
    showListWithAllFormErrors: true,
    scrollToFirstError: true,
    validateOnBlur: true
  },
  translations: {
    en: {
      optional: 'Optional',
      months: [
        'January',
        'February',
        'March',
        'April',
        'May',
        'June',
        'July',
        'August',
        'September',
        'October',
        'November',
        'December'
      ],
      days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      showPassword: 'Show password',
      hidePassword: 'Hide password'
    }
  },
  classNames: {
    prefix: classNamePrefix,
    form: {
      default: `${classNamePrefix}form`
    },
    fieldset: {
      default: `${classNamePrefix}fieldset`,
      legend: `${classNamePrefix}legend`
    },
    group: {
      default: `${classNamePrefix}elements`
    },
    inputs: {
      container: `${classNamePrefix}input-container`,
      group: `${classNamePrefix}input-group`,
      label: `${classNamePrefix}label`,
      description: `${classNamePrefix}description`,
      text: `${classNamePrefix}input`,
      inputContainer: `${classNamePrefix}input-container`,
      passwordToggle: `${classNamePrefix}password-toggle`,
      error: `${classNamePrefix}has-error`,
      optional: `${classNamePrefix}optional`
    },
    date: {
      container: `${classNamePrefix}date`,
      trigger: `${classNamePrefix}calendar-trigger`,
      calendar: `${classNamePrefix}calendar`
    },
    list: {
      container: `${classNamePrefix}list`,
      item: `${classNamePrefix}list-item`,
      label: `${classNamePrefix}list-item-label`,
      input: `${classNamePrefix}list-item-input`
    },
    range: {
      container: `${classNamePrefix}range`,
      inputContainer: `${classNamePrefix}range-input-container`,
      input: `${classNamePrefix}range-input`,
      indicator: `${classNamePrefix}range-indicator`,
      minLabel: `${classNamePrefix}range-min-label`,
      maxLabel: `${classNamePrefix}range-max-label`
    },
    select: {
      container: `${classNamePrefix}select-container`,
      item: `${classNamePrefix}select`
    },
    buttons: {
      container: `${classNamePrefix}buttons`,
      submit: `${classNamePrefix}button-submit`,
      reset: `${classNamePrefix}button-reset`,
      back: `${classNamePrefix}button-back`
    },
    errors: {
      group: `${classNamePrefix}errors`,
      error: `${classNamePrefix}error`
    }
  }
}

Pass the config by framework

Vue and Nuxt

<script setup lang="ts">
import { config } from './jcees-forms.config'
</script>

<template>
  <JCeesForms
    space="your-space-id"
    form="your-form-id"
    language="en"
    :config="config"
  />
</template>

React

import JCeesForms from '@jcees-forms/react'
import { config } from './jcees-forms.config'

export default function Form() {
  return <JCeesForms space="your-space-id" form="your-form-id" config={config} />
}

Next.js

A serializable config can be passed to the default server component. If callbacks are required, pass the same config to JCeesFormsClient inside your client component.

import JCeesForms from '@jcees-forms/next'
import { config } from './jcees-forms.config'

export default function Page() {
  return <JCeesForms space="your-space-id" form="your-form-id" config={config} />
}

JavaScript

import { JCeesForm } from '@jcees-forms/javascript'
import { config } from './jcees-forms.config'

const form = new JCeesForm({
  spaceId: 'your-space-id',
  formId: 'your-form-id',
  language: 'en',
  config
})