Class FormDef
- All Implemented Interfaces:
Widget
present=dialog action).
A widget contract driven by a view-module runtime
Like ModalDef, this is a general widget contract that lives in this module while the browser runtime that
paints it ships with the rich-view module. Nothing here depends on that module.
Flat or sectioned
A form declares either a flat fields list or an ordered list of FormDef.Sections, never both: the flat list
is the single-section case. Sections render as a ribbon-format strip above one visible pane; they are a
layout of one dialog, not a stack of dialogs, so they cost nothing against the runtime's modal-depth cap.
Typed inputs, not markup
The client paints fields as native <input> / <textarea> / <select> /
<button> elements via createElement. Labels and option text use textContent; prefills use
.value / .checked. The runtime never assigns innerHTML from this payload. Only the
types on the allowlist (text, textarea, password, checkbox, toggle, select,
action) are legal — that is the XSS bound: hostile prefill cannot become an element.
template may name a server-side template for authors. It is not a client HTML sink; the
shipped juneau-views.js ignores it.
Per-widget contract version (fail-loud when a form is present)
This bean validates fail-closed and carries an instance contractVersion. The
version defaults to CONTRACT_VERSION from the instant the form is constructed — a raw
builder no longer leaks an unversioned form regardless of whether checked() is invoked. The client
refuses to open a form-bearing dialog whose version does not match the one its runtime bakes in.
This constant moves in lockstep with ModalDef.CONTRACT_VERSION and the runtime's baked-in literal,
because the runtime compares one literal against both the modal's and the form's version. Bumping any two of the
three makes every form-bearing dialog refuse to open.
Example:
FormDef
See Also:
- Since:
- 10.0.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classA single typed form input painted client-side withcreateElement(neverinnerHTML).static classOne labelled group of inputs inside a sectioned form: the multi-page dialog shape. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe frozen form contract version.The frozen form contract version discriminator.Typed inputs in display order for a flat, single-section form; omitted from the wire when none are declared.Optional ordered sections for a multi-section form; omitted from the wire when none are declared.Optional FreeMarker template reference for server authors; ignored by the client. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionchecked()The serving-path hook: re-stampsCONTRACT_VERSION(already set by construction; this repairs a version a caller explicitly cleared) thenvalidates.static FormDefcreate()field(FormDef.Input value) Adds one typed input field.static FormDefofTemplate(String template) Creates a form sourced from the specified FreeMarker template reference.section(FormDef.Section value) Adds one section, making this a multi-section form.Sets the optional server-author template reference.voidvalidate()Fail-closed bean validation.
-
Field Details
-
CONTRACT_VERSION
The frozen form contract version. Bumped only on a breaking wire change to this form contract.- See Also:
-
contractVersion
The frozen form contract version discriminator.Defaults to
CONTRACT_VERSIONfrom the instant this form is constructed, independent ofchecked(). Guaranteed present is not the same as guaranteed valid: presence is this field's whole job, structural well-formedness isvalidate()'s (seechecked()). -
template
Optional FreeMarker template reference for server authors; ignored by the client. -
fields
Typed inputs in display order for a flat, single-section form; omitted from the wire when none are declared.Mutually exclusive with
sections— a flatfieldslist is the single-section case, so declaring both is an authoring errorvalidate()rejects rather than silently picking one. -
sections
Optional ordered sections for a multi-section form; omitted from the wire when none are declared.Mutually exclusive with
fields(see that field). A single-elementsectionslist is legal but pointless: it renders a one-tab strip where a flatfieldslist would render none.
-
-
Constructor Details
-
FormDef
public FormDef()
-
-
Method Details
-
create
- Returns:
- A new
FormDef.
-
ofTemplate
Creates a form sourced from the specified FreeMarker template reference.- Parameters:
template- The template reference (a resolvable URL/name). Must not benull or blank.- Returns:
- A new
FormDef. - Throws:
IllegalArgumentException- Iftemplateisnull or blank.
-
template
Sets the optional server-author template reference. The client never treats this as HTML.- Parameters:
value- The template reference. Must not benull or blank.- Returns:
- This object.
- Throws:
IllegalArgumentException- Ifvalueisnull or blank.
-
field
Adds one typed input field.- Parameters:
value- The input. Must not benull .- Returns:
- This object.
- Throws:
IllegalArgumentException- Ifvalueisnull .
-
section
Adds one section, making this a multi-section form.- Parameters:
value- The section. Must not benull .- Returns:
- This object.
- Throws:
IllegalArgumentException- Ifvalueisnull .
-
validate
Fail-closed bean validation.Does not require
contractVersionto already be set — a raw-built form validated directly must not false-refuse on a null version. A form with neitherfieldsnorsectionsis a no-op (a template-only / fieldless form is a shipped shape).Field names are unique across the whole form, not per section: every control shares one submit body and one dialog-scoped element-id namespace, so two sections declaring the same name would collide in both.
-
checked
The serving-path hook: re-stampsCONTRACT_VERSION(already set by construction; this repairs a version a caller explicitly cleared) thenvalidates.contractVersionno longer depends on this being called. Structural validation no longer depends on it either for a form served over REST: nested inside a returnedModalDef, this form is reached byWidgetsMixin.WidgetValidationProcessor's call toModalDef.validate(), which recurses into this bean's ownvalidate(), fail-closed with a 500, whether or not the producing endpoint calledModalDef.checked(). This method (viaModalDef.checked()) remains the only fail-closed structuralvalidationa non-REST producer has — a directJson.of(...)serialization, for instance — and calling it for a REST-bound form stays safe (validation is idempotent) even though it is no longer strictly required there.- Returns:
- This object.
- Throws:
IllegalArgumentException- If this form is not well-formed.
-