Skip to main content

Form

Form collects, validates, and submits a related set of fields. Use it for requests, registration, settings, record editing, and workflow steps. A Form owns its field groups, layout, validation state, and submission scope; it is more than a visual row of inputs.

This guide explains how to:

  • Organize a long Form with sections
  • Set controls per row and the label/content grid split
  • Make a descriptive field span the full row while preserving label alignment
  • Add required, length, pattern, and numeric-range validation
  • Configure Reset, Validate, and Submit actions
  • Submit only the selected Form instead of all page state
  • Let a Java backend distinguish environment and render mode

1. Form capabilities and configuration​

Form configuration has four levels:

  1. Form owns layout, mode, data loading, submission, drafts, and public state.
  2. Form Section groups fields by business topic and can represent a repeatable collection.
  3. Field defines the label, Field Key, default value, row span, conditional behavior, and validators.
  4. Button Set / Interaction orchestrates Reset, Validate, Submit, and component functions.

1.1 Property and feature overview​

AreaMain properties or featuresPurpose
StructureID / Name, Form Sections, Fields, Button SetDefine the Form boundary, business groups, and submission scope
LayoutControls Per Row, Form column split, Layout, Label Alignment, Full rowControl field density, label width, arrangement, and full-row fields
ModeCreate, Edit, View, Warn about unsaved changesSupport create, edit, read-only, and navigation protection
Data adapterLoad / Create / Update URL, Response Data Path, Record ID, RevisionLoad records and connect create, update, and optimistic-lock APIs
SubmissionFull values, Changed values only, Custom URLSubmit the complete Form or only changed fields
ValidationRequired, Length, Pattern, Number, Custom Validator, Remote validationProvide immediate, remote, and server-side field feedback
ConditionsVisible / Disabled / Required When, Dependencies, Clear When HiddenReact to other fields, Page Context, or the current mode
Repeatable groupCollection Key, Minimum / Maximum Items, Add / DeleteEdit object arrays such as contacts or line items
DraftsBrowser / Remote storage, Draft Key, Autosave Delay, revisionSave, restore, or discard unfinished work
Actions and statereset, validate, submit, saveDraft, restoreDraft, discardDraft; forms.*Orchestrate actions and read valid, dirty, or submitting state
Field generationBusiness Object, JSON Schema, OpenAPIGenerate an editable field structure from an existing model

1.2 Structure and submission boundary​

A Form is both a state boundary and a submission boundary. A page can contain several Forms, and each Form owns only its own Sections, Fields, and Button Set:

  • A Form Section expresses a business group such as Basic information or Access; it is not merely visual spacing.
  • A Field Key is the stable property name in Form state and submitted JSON, and should match the backend DTO.
  • A Button Set places the actions, while Interaction decides whether a button runs Reset, Validate, or Submit.
  • Submit Form collects only registered fields from the selected Form. It does not automatically include another Form, Page Context, or Tree Current Record.

When one page contains a search Form and an edit Form, assign separate IDs and point every action to its intended Form. Visual proximity does not define submission ownership.

1.3 Layout and responsive behavior​

One shared layout contract controls all ordinary fields:

  • Controls Per Row sets the maximum number of fields per row and therefore the grid width available to each field.
  • Form column split divides that field area between Label and Content. With two controls per row, the two values total 12; with one control, they total 24.
  • Layout supports Horizontal, Vertical, and Inline. Label Alignment affects label text only in Horizontal layout.
  • Full row / Start on new row lets a long field span the row while keeping its label aligned with the first normal field.
  • On narrow screens, fields stack in reading order; a separate mobile Form is unnecessary.

The Form owns the layout, while a Field only declares whether it starts a new row or spans the row. Changing Controls Per Row can therefore recalculate the complete structure consistently.

1.4 Modes, data loading, and submission​

Form capabilities applies one field structure to three lifecycles:

ModePage behaviorTypical endpoint
CreateStart from defaults and create a recordCreate URL, normally POST
EditLoad a record, then submit modificationsLoad URL + Update URL, normally PUT / PATCH
ViewReuse the label/value layout as read-only contentLoad URL, without editing actions

The Data adapter uses Response Data Path to find the record and keeps Record ID Field and Revision Field for identity and optimistic locking. Loaded values become the baseline used by Reset and Changed values only.

Use a Submit Form Custom URL for a simple one-off request. Use the full Data adapter when the page must load, edit, detect conflicts, or restore drafts. Warn about unsaved changes is triggered only when values differ from the baseline.

1.5 Validation, field errors, and conditions​

Validation has three layers:

  1. Local rules such as Required, Length, Pattern, Number, and Custom Validator provide immediate feedback.
  2. Remote validation checks values such as usernames, email addresses, or business codes through a backend request with a configurable trigger and debounce.
  3. Submit validation maps a top-level backend fieldErrors object back to fields by Field Key while retaining the overall displayText.

Fields can also use Visible When, Disabled When, and Required When. Expressions read state.*, context.*, record.*, or form.*; Dependencies declares which Field Keys trigger reevaluation. Clear When Hidden removes stale hidden values before submission.

Client validation improves feedback but never replaces backend validation, authorization, or auditing. Hiding a field is not an access-control boundary.

1.6 Repeatable groups and drafts​

A Form Section can become a repeatable group. Its Fields form the row template, and Collection Key becomes an object array in submitted JSON. Minimum / Maximum Items constrain row count, while Runtime provides Add / Delete. Validation paths retain array indexes so a specific row can be identified.

Drafts preserve unfinished Form state rather than the saved business record:

  • Browser storage suits short-lived, single-device work.
  • Remote service supports important or cross-device work through Load / Save URL, Draft Key, and revision.
  • Autosave Delay controls when an idle edit is saved. A remote revision conflict must ask the user to reload or restore instead of silently overwriting data.

1.7 Actions and public state​

Common Form operations can be used by buttons, Steps, or any Interaction chain:

OperationBehavior
resetRestore the loaded baseline or Create defaults and clear validation messages
validateValidate the current Form and stop later actions on failure
submitValidate, build the payload, send the request, and process field errors
saveDraft / restoreDraft / discardDraftSave, restore, or discard a draft

Expressions can read forms.<formId>.valid, dirty, submitting, submitError, lastSubmit, and mode. For example, disable Submit while submitting, or run Submit Form before a Step nextStep. The Form owns these read-only states; page actions should not mutate them directly.

1.8 Field generation and backend cooperation​

Generate fields creates Sections and Fields from a Business Object, JSON Schema, or OpenAPI Schema. The result is normal editable page metadata, so designers can still refine labels, control types, options, layout, and validation. Always review sensitive fields, enum labels, permissions, and endpoint settings after generation.

Data loading, remote validation, drafts, and submission all receive platform-managed request context:

X-Spark-Page-Environment: DEV | TEST | PROD
X-Spark-Page-Render-Mode: DESIGN_PREVIEW | RUNTIME

A backend can return stable sandbox data in DESIGN_PREVIEW and execute the real use case in RUNTIME. Environment and render mode guide debugging; they do not replace authentication, tenant isolation, or authorization.

1.9 Choose a configuration path​

GoalRecommended starting pointContinue with
Basic create FormCreate + Sections + local validation + Custom URLSections 2–8
Edit an existing recordEdit + Load / Update URL + Record ID / RevisionSections 9, 10, and 14
Read-only detailView + Load URLSections 10 and 17
Dynamic fieldsConditions + DependenciesSections 11 and 12
Contacts or line itemsRepeatable GroupSection 13
Long-running inputDraft + Warn about unsaved changesSection 15
Build from an existing modelGenerate fieldsSection 16
Form inside a workflow StepValidate / Submit → Step nextStepSections 7 and 17

1.10 Fields available in Form​

Choose a field from the data shape first, then configure layout, validation, and Interaction. The field palette currently exposes the 22 components below. Legacy Select, MultiSelect, and the old MultiRowInput remain hidden for compatibility with existing pages and are not new-page entry points.

CategoryField componentsSuitable data
Basic inputInput, Address, Text AreaSingle-line text, addresses, and long text
Selection and peopleSelect, Radio Button, Checkbox, Switch, Cascade Select, Tree Select, Transfer, User Select, Department SelectEnums, hierarchies, sets, user IDs, and department IDs
Date and numericDate Picker, Time Picker, Calendar, Rate, SliderDates, times, ratings, numbers, and ranges
EditorsRich Text, Code Editor, JSON EditorFormatted content, scripts, and JSON
Files and structured dataUpload, Multi-Row InputFile metadata and object arrays

Each field guide explains use cases, main properties, submitted value shape, conditions, and Interaction. Choose the component from the backend data contract, not from appearance alone.

2. Sample: employee onboarding request​

The Form page in Spark Sample contains two sections, a two-column layout, a full-row justification field, and Reset, Validate, and Submit actions.

Screen
└── Form: Employee Onboarding Form
├── Form Section: Employee details
│ ├── Full name / Work email / Department
│ └── Employment type / Start date
├── Form Section: Equipment and access
│ ├── Laptop budget / Administrator access
│ └── Request justification (full row)
└── Button Set: Reset / Validate / Submit request

The sample starts with representative values so you can immediately inspect validation and submission. Clear them for a create page, or populate them from a record on an edit page.

3. Add the Form and sections​

  1. Add Form to a Screen, Panel, Grid Column, Tab, Step, or Content.
  2. Select the Form and add one or more items under Form Sections.
  3. Select a section and add Field, Select, RadioBox, DatePicker, Switch, TextArea, or other fields under Fields.
  4. Add actions to the Form's Button Set.
  5. Give the Form and each field a stable ID and Name, then save and inspect both Design Mode and Runtime.

Use sections for business meaning, such as Basic information, Access, Attachments, and Confirmation. Do not add empty sections only to create visual spacing.

4. Configure the layout​

Controls Per Row sets the maximum number of ordinary fields in a row. One is suitable for long content, two is a good default for desktop business forms, and three or four should be limited to compact filters and short values. Narrow screens stack fields in reading order.

The Form uses a 24-column grid, but the split is calculated inside each field area. With two controls per row, one normal field receives 12 columns, so the label and content should total 12:

Label 4 + Content 8 = 12

With one control per row, use a total of 24, such as 6 + 18. Dragging Form column split changes both values together.

Enable Start on new row / Full row for a TextArea or another field that needs more room. Its label retains the Form label ratio and aligns with the first label above; the content spans the remaining columns.

Layout options:

LayoutUse
HorizontalLabel and control share a row; preferred for desktop business forms
VerticalLabel sits above the control; useful in narrow containers or with long labels
InlineFields and buttons flow in one line; intended for short search/filter bars

5. Reproduce the sample fields​

FieldComponentImportant settings
Full nameFieldRequired; Length 2–60
Work emailFieldRequired; email Pattern
DepartmentSelectEngineering, Product, Sales, Operations
Employment typeRadioBoxFull time, Contractor, Intern
Start dateDatePickerYYYY-MM-DD
Laptop budgetNumber FieldRequired; range 500–5000; suffix USD
Administrator accessSwitchDefault Checked off
Request justificationTextAreaFull row; initial height 4; maximum 8; Length 20–500

Name / Field Key becomes the JSON property sent to the backend. Each editable field in a Form must use a unique key.

6. Validation​

Use Required for missing values, Length for string bounds, Pattern for formats such as email, Number for numeric bounds, and Custom Validator for business rules. When validation fails, Spark highlights the specific field and stops submission.

Client-side validation gives immediate feedback. The backend must keep equivalent validation because browser requests can bypass the page.

7. Reset, Validate, and Submit​

For Reset, add Call Component Function to the button's onClick:

Component: employee_onboarding_form
Function: reset

Reset restores initial values and clears validation messages; it does not always produce empty values.

For Validate, add Validate Form and choose employee_onboarding_form. Later actions run only after successful validation.

For Submit, add Submit Form:

Form: employee_onboarding_form
Submission Mode: Custom URL
URL: /spark/api/sample/form/requests
Method: POST

Spark validates the selected Form, collects only fields registered to that Form, posts the JSON body, and then displays the backend displayText or runs configured success actions. Other Forms, Page Context, and a Tree Current Record are not mixed into the payload.

8. Java backend​

Use the shared header contract and return ApiResult<DTO>:

@PostMapping
public ApiResult<FormRequestReceiptDTO> submit(
@RequestBody FormRequestSubmission request,
@RequestHeader(value = SparkPageRequestHeaders.ENVIRONMENT,
required = false) String environment,
@RequestHeader(value = SparkPageRequestHeaders.RENDER_MODE,
required = false) String renderMode) {
SparkPageRequestContext context =
SparkPageRequestHeaders.resolve(environment, renderMode);
return SparkApiResultHelper.success(
Locale.ENGLISH,
requestService.submit(request, context),
"SPARK-SAMPLE-FORM-0001");
}

The service can return a safe, non-persistent receipt during Design Preview and execute the real use case during Runtime:

boolean preview = context.getRenderMode()
== SparkPageRenderMode.DESIGN_PREVIEW;
return preview
? previewReceipt(request, context)
: onboardingUseCase.submit(request, context.getEnvironment());

Spark adds X-Spark-Page-Environment: DEV | TEST | PROD and X-Spark-Page-Render-Mode: DESIGN_PREVIEW | RUNTIME centrally. Do not duplicate these headers in each Interaction. See Page request context and backend debugging.

9. Advanced sample: employee profile editor​

The second sample adds a complete edit lifecycle: it loads a record, validates email remotely, conditionally displays the administrator-access reason, lets users add emergency contacts, autosaves drafts, and submits only changed values.

The reproducible page JSON is spark-sample/src/main/resources/samples/form-capabilities-page.json; its backend is FormCapabilityController and FormCapabilitySampleService.

10. Modes and public state​

Select the Form and open Form capabilities:

ModeBehavior
CreateUse defaults and submit to Create URL
EditLoad a record from Load URL and submit to Update URL
ViewKeep the same layout but render read-only values

Enable Warn about unsaved changes to confirm before leaving a dirty page. Each Form exposes read-only state for expressions and actions:

forms.employee_profile_form.valid
forms.employee_profile_form.dirty
forms.employee_profile_form.submitting
forms.employee_profile_form.submitError
forms.employee_profile_form.lastSubmit
forms.employee_profile_form.mode

Inside the Form, use form.dirty or form.submitting for the current Form. Do not assign these values directly.

11. Conditional fields​

The Access reason field uses:

Visible When: state.adminAccess === true
Required When: state.adminAccess === true
Dependencies: adminAccess
Clear When Hidden: on

Visible When, Disabled When, and Required When accept boolean expressions over state.*, context.*, record.*, and form.*. Dependencies are comma-separated stable Field Keys. Clear When Hidden prevents stale hidden data from being submitted.

12. Remote and server validation​

Add Remote validation under Work email → Validators:

Validation URL: /spark/api/sample/form/validate-email
Method: POST
Debounce: 400
Value Parameter: value
Valid Response Path: data.valid
Message Response Path: data.message
Trigger: blur

New input cancels the previous request and stale responses are ignored. Submission-time business validation returns field errors at the top level:

{
"success": false,
"displayText": "Review the highlighted form fields and try again.",
"fieldErrors": {
"workEmail": ["This email address is already used."],
"adminAccessReason": ["Explain why administrator access is required."]
}
}

Spark maps these messages back to Form Items. Java services can throw SparkFieldValidationException with Lattice Message values so the web boundary localizes every field message.

13. Repeatable groups​

Select a Form Section and enable Repeatable Group:

Collection Key: emergencyContacts
Minimum Items: 1
Maximum Items: 3
Add Button Text: Add contact

Fields in the section become a row template. Runtime supplies Add/Delete and submits an array under the Collection Key. View mode hides editing actions.

14. Data adapter and change sets​

Configure the advanced sample under Form capabilities → Lifecycle:

Load URL: /spark/api/sample/form/records/employee-1001
Create URL: /spark/api/sample/form/records
Update URL: /spark/api/sample/form/records/[[state.id]]
Response Data Path: data
Submission Payload: Changed values only
Record ID Field: id
Revision Field: revision

Edit mode establishes a baseline after loading. Changed-values submission sends:

{
"recordId": "employee-1001",
"revision": 3,
"changes": [
{ "op": "replace", "path": "/department", "value": "PRODUCT" }
]
}

Create mode always sends complete values. Use revision for optimistic locking and return HTTP 409 instead of silently overwriting a newer record.

15. Draft autosave​

Use browser storage for personal temporary input, or a remote service for cross-device and important flows. The sample uses:

Storage: Remote service
Draft Key: employee-1001
Load URL: /spark/api/sample/form/drafts/employee-1001
Save URL: /spark/api/sample/form/drafts/employee-1001
Autosave Delay: 1500 ms

Form also exposes saveDraft, restoreDraft, and discardDraft component functions. Remote drafts must return a revision; an outdated revision receives HTTP 409 and is not overwritten.

16. Generate fields from a model or schema​

Open Form capabilities → Generate fields and choose Business Object, JSON Schema, or OpenAPI. For OpenAPI, optionally enter a path such as #/components/schemas/Employee. Choose append or replace, generate, review the count, and save.

Object arrays become Repeatable Groups. Generation creates ordinary editable page metadata; Runtime never executes arbitrary component JSON or scripts returned by a backend. Always review labels, sensitive fields, options, layout, permissions, URLs, and server validation.

17. Common scenarios​

  • Use View mode for a details page.
  • Use Create plus Create URL for a new record.
  • Use Edit plus Load/Update URLs and revision for editing.
  • Put a separate Form in each Step; failed validation or submission interrupts the later Next action.
  • Use Inline only for a small filter bar.
  • Enable drafts and unsaved warnings for long-running work.

18. Troubleshooting​

  • Labels do not align: With two controls per row, use a split that totals 12, such as 4 + 8. A full-row field keeps Label 4 automatically.
  • Layout preview does not change: Select the Form, save the page, and check whether a narrow parent column has triggered responsive stacking.
  • A visible default still fails Required: Save the latest page and confirm Runtime uses the same version; displayed defaults participate in the same validation and submission state.
  • Unexpected fields are submitted: Check the target Form and unique Field Keys. Correct submission is Form-scoped.
  • Design Preview must not create records: Branch on DESIGN_PREVIEW in the backend and return a preview receipt or use a sandbox; Runtime still requires authorization and audit.
  • A conditional field does not update: Put the controlling Field Key in Dependencies and reference the key, not its display label.
  • Server errors appear only at the top: Return top-level fieldErrors whose keys exactly match Form Field Keys.
  • Draft conflicts repeat: Return a new revision after saving and send that revision with the next request; load an existing remote draft before overwriting it.