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:
- Form owns layout, mode, data loading, submission, drafts, and public state.
- Form Section groups fields by business topic and can represent a repeatable collection.
- Field defines the label, Field Key, default value, row span, conditional behavior, and validators.
- Button Set / Interaction orchestrates Reset, Validate, Submit, and component functions.
1.1 Property and feature overview
| Area | Main properties or features | Purpose |
|---|---|---|
| Structure | ID / Name, Form Sections, Fields, Button Set | Define the Form boundary, business groups, and submission scope |
| Layout | Controls Per Row, Form column split, Layout, Label Alignment, Full row | Control field density, label width, arrangement, and full-row fields |
| Mode | Create, Edit, View, Warn about unsaved changes | Support create, edit, read-only, and navigation protection |
| Data adapter | Load / Create / Update URL, Response Data Path, Record ID, Revision | Load records and connect create, update, and optimistic-lock APIs |
| Submission | Full values, Changed values only, Custom URL | Submit the complete Form or only changed fields |
| Validation | Required, Length, Pattern, Number, Custom Validator, Remote validation | Provide immediate, remote, and server-side field feedback |
| Conditions | Visible / Disabled / Required When, Dependencies, Clear When Hidden | React to other fields, Page Context, or the current mode |
| Repeatable group | Collection Key, Minimum / Maximum Items, Add / Delete | Edit object arrays such as contacts or line items |
| Drafts | Browser / Remote storage, Draft Key, Autosave Delay, revision | Save, restore, or discard unfinished work |
| Actions and state | reset, validate, submit, saveDraft, restoreDraft, discardDraft; forms.* | Orchestrate actions and read valid, dirty, or submitting state |
| Field generation | Business Object, JSON Schema, OpenAPI | Generate 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:
| Mode | Page behavior | Typical endpoint |
|---|---|---|
| Create | Start from defaults and create a record | Create URL, normally POST |
| Edit | Load a record, then submit modifications | Load URL + Update URL, normally PUT / PATCH |
| View | Reuse the label/value layout as read-only content | Load 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:
- Local rules such as Required, Length, Pattern, Number, and Custom Validator provide immediate feedback.
- Remote validation checks values such as usernames, email addresses, or business codes through a backend request with a configurable trigger and debounce.
- Submit validation maps a top-level backend
fieldErrorsobject back to fields by Field Key while retaining the overalldisplayText.
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:
| Operation | Behavior |
|---|---|
reset | Restore the loaded baseline or Create defaults and clear validation messages |
validate | Validate the current Form and stop later actions on failure |
submit | Validate, build the payload, send the request, and process field errors |
saveDraft / restoreDraft / discardDraft | Save, 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
| Goal | Recommended starting point | Continue with |
|---|---|---|
| Basic create Form | Create + Sections + local validation + Custom URL | Sections 2–8 |
| Edit an existing record | Edit + Load / Update URL + Record ID / Revision | Sections 9, 10, and 14 |
| Read-only detail | View + Load URL | Sections 10 and 17 |
| Dynamic fields | Conditions + Dependencies | Sections 11 and 12 |
| Contacts or line items | Repeatable Group | Section 13 |
| Long-running input | Draft + Warn about unsaved changes | Section 15 |
| Build from an existing model | Generate fields | Section 16 |
| Form inside a workflow Step | Validate / Submit → Step nextStep | Sections 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.
| Category | Field components | Suitable data |
|---|---|---|
| Basic input | Input, Address, Text Area | Single-line text, addresses, and long text |
| Selection and people | Select, Radio Button, Checkbox, Switch, Cascade Select, Tree Select, Transfer, User Select, Department Select | Enums, hierarchies, sets, user IDs, and department IDs |
| Date and numeric | Date Picker, Time Picker, Calendar, Rate, Slider | Dates, times, ratings, numbers, and ranges |
| Editors | Rich Text, Code Editor, JSON Editor | Formatted content, scripts, and JSON |
| Files and structured data | Upload, Multi-Row Input | File 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
- Add Form to a Screen, Panel, Grid Column, Tab, Step, or Content.
- Select the Form and add one or more items under Form Sections.
- Select a section and add Field, Select, RadioBox, DatePicker, Switch, TextArea, or other fields under Fields.
- Add actions to the Form's Button Set.
- 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:
| Layout | Use |
|---|---|
| Horizontal | Label and control share a row; preferred for desktop business forms |
| Vertical | Label sits above the control; useful in narrow containers or with long labels |
| Inline | Fields and buttons flow in one line; intended for short search/filter bars |
5. Reproduce the sample fields
| Field | Component | Important settings |
|---|---|---|
| Full name | Field | Required; Length 2–60 |
| Work email | Field | Required; email Pattern |
| Department | Select | Engineering, Product, Sales, Operations |
| Employment type | RadioBox | Full time, Contractor, Intern |
| Start date | DatePicker | YYYY-MM-DD |
| Laptop budget | Number Field | Required; range 500–5000; suffix USD |
| Administrator access | Switch | Default Checked off |
| Request justification | TextArea | Full 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:
| Mode | Behavior |
|---|---|
| Create | Use defaults and submit to Create URL |
| Edit | Load a record from Load URL and submit to Update URL |
| View | Keep 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_PREVIEWin 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
fieldErrorswhose 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.