Skip to content

Form Configuration Guide

@enlolab/forms provides a simple and declarative way to create complex forms. The main configuration is done through the FormConfig object.

const myForm = FormFactory({
formId: "my-form",
fields: {
// Field configuration
},
steps: {
// Steps configuration
},
layout: {
// Layout configuration
},
submit: {
// Submit configuration
},
buttons: {
// Button configuration
},
});

Below is a high-level overview of every top-level key inside FormConfig:

PropertyTypeRequiredDescription
formIdstringYesUnique identifier passed to the backend and DOM.
fieldsRecord<string, FieldConfig>YesDeclarative configuration for every field in the form.
stepsRecord<string, Step>YesDefines the navigation flow and conditional branching.
layoutLayoutConfigNoControls the grid columns, gaps and container classes.
submitSubmitConfigNoDetermines how data is sent (default, recaptcha, custom).
buttonsFormButtonsNoOverrides labels, variants and actions for Submit, Next, Back.
successMessagestring | (values) => stringNoHTML or function returning the success message.
errorMessagestring | (error, values) => stringNoCustom message when submission fails.
onStepChange(stepId) => voidNoCallback executed whenever the current step changes.
onSuccess(values) => voidNoCallback after a successful submission.
onError(error, values) => voidNoCallback when the submission throws.

@enlolab/forms ships with three submission strategies:

TypereCAPTCHAWhen to usePayload
default✔️Production forms that require bot protectionclientId, formId, data, recaptchaToken
default-no-recaptcha✖️Internal tools or low-risk environmentsclientId, formId, data
customN/AFull control over networking logicWhatever you send from onSubmit

Example using the built-in endpoint + reCAPTCHA:

submit: {
type: "default",
endpoint: {
url: "https://api.yourapp.com/forms/submit",
clientId: "marketing-site" // optional
},
recaptcha: {
siteKey: "YOUR_SITE_KEY",
action: "submit"
}
}

If you need advanced logic, switch to custom:

submit: {
type: "custom",
onSubmit: async (values) => {
await fetch("/api/contact", {
method: "POST",
body: JSON.stringify(values),
headers: { "Content-Type": "application/json" }
});
}
}

Form buttons configuration:

buttons: {
submit: {
label: "Submit",
variant: "default"
},
next: {
label: "Next",
variant: "outline"
},
back: {
label: "Back",
variant: "ghost"
}
}

You can customize success and error messages in two ways:

Simple string messages:

successMessage: "Form submitted successfully!",
errorMessage: "An error occurred while submitting the form"

You can use functions to generate messages dynamically based on form values:

successMessage: (values) => `✅ Thanks <strong>${values.name}</strong>, we'll be in touch!`,
errorMessage: (error, values) => `❌ Oops: ${error.message}`

The function receives:

  • For successMessage: values: Record<string, unknown> - all form field values
  • For errorMessage: error: Error and values: Record<string, unknown>

You can access any field value from the values object (e.g., values.email, values.transport). The returned string can contain HTML tags that will be safely rendered.

Tip: All callbacks receive the latest form values so you can call analytics or mutate state outside the form.

@enlolab/forms provides several callbacks to handle important events: