morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
morph::forms::FieldMeta Struct Reference

Per-field presentation overrides and scalar bounds: label, help, placeholder, read-only, hidden, minimum/maximum/multipleOf, and a plain member's display unit/decimals (docs/spec/forms/forms.md, "Field metadata"). More...

#include <forms.hpp>

Public Member Functions

constexpr FieldMeta withPlaceholder (std::string_view text) const noexcept
 Returns a copy with placeholder set to text.
constexpr FieldMeta withReadOnly () const noexcept
 Returns a copy with readOnly set to true.
constexpr FieldMeta withHidden () const noexcept
 Returns a copy with hidden set to true.
constexpr FieldMeta withMinimum (::morph::math::Rational bound) const noexcept
 Returns a copy with minimum set to bound.
constexpr FieldMeta withMaximum (::morph::math::Rational bound) const noexcept
 Returns a copy with maximum set to bound.
constexpr FieldMeta withMultipleOf (::morph::math::Rational step) const noexcept
 Returns a copy with multipleOf set to step.
constexpr FieldMeta withUnit (std::string_view text) const noexcept
 Returns a copy with unit set to text.
constexpr FieldMeta withDecimals (::morph::math::DecimalPlaces places) const noexcept
 Returns a copy with decimals set to places.
constexpr FieldMeta withBlankAs (BlankAs mode) const noexcept
 Returns a copy with blankAs set to mode.

Public Attributes

std::string_view field
 Wire key of the member this entry describes.
std::string_view label {}
 Display label; empty infers a title-cased name from field.
std::string_view help {}
 Help text; empty omits description.
std::string_view placeholder {}
 In-control placeholder hint; empty omits x-placeholder.
std::string_view i18nKey {}
 Explicit message-key stem override for this field's i18n catalog keys; empty means "derive the stem from the action's `ActionTraits<A>::typeId()` and this field's wire key" (see morph::forms::i18n::fieldKey, forms/i18n.hpp). A non-empty stem replaces only the <actionTypeId>.<wireField> portion of the key — the per-slot .label / .help / .placeholder suffix is still appended on top of it (see morph::forms::i18n::explicitFieldKey), so "myKey" expands to "myKey.label" / "myKey.help" / "myKey.placeholder", never to a single complete key on its own. Emitted as x-i18nKey only when non-empty.
std::string_view widget {}
 Widget-selection override; empty means "use the field type's own `widget()`, if any". A non-empty value replaces that type-derived default and is emitted as x-widget (docs/spec/forms/widget_hints.md). Read structurally by detail::widgetOverride, not through this type by name — see detail::HasFieldMetadataWidgets.
bool readOnly {false}
 Displayed but not editable when true; emits x-readonly.
bool hidden {false}
 Not shown at all when true; emits x-hidden. The field still travels in the payload (see docs/spec/forms/forms.md, "Field metadata is not a security control").
std::optional<::morph::math::Rational > minimum {}
 Inclusive lower bound on the field's numeric value; emitted as the standard JSON-Schema minimum. Disengaged means "no floor".
std::optional<::morph::math::Rational > maximum {}
 Inclusive upper bound on the field's numeric value; emitted as the standard JSON-Schema maximum. Disengaged means "no ceiling". Same canonical-unit reading as minimum.
std::optional<::morph::math::Rational > multipleOf {}
 The field's value must be an exact integer multiple of this; emitted as the standard JSON-Schema multipleOf. Disengaged means "any value".
std::string_view unit {}
 Display unit for a member whose C++ type carries none (a plain double, float or integral member); emitted as the property's ExtUnits ({"unitAscii": unit, "unitUnicode": unit}), the key a Quantity already carries. Empty emits nothing.
std::optional<::morph::math::DecimalPlaces > decimals {}
 Display and entry precision: for a plain double/float member emitted as x-displayDecimals, for a bare math::Rational member as x-decimalPlaces. Disengaged emits nothing.
BlankAs blankAs {BlankAs::Omit}
 What a blank control submits for a std::string / std::optional<std::string> member; BlankAs::Empty emits "x-blankAs": "empty".
std::string_view optionsAction {}
 Type id of the registered action whose result rows are this member's options, for a member that is not a Choice<…>: the member is emitted with x-optionsAction, x-optionValue and x-optionLabel, as a Choice is, so a renderer draws it as a lookup select. Empty emits nothing. Set together with valueField and labelField; a Choice member, whose type already names its options, refuses it.
std::string_view valueField {}
 Field of each options row submitted as the value (x-optionValue); set with optionsAction.
std::string_view labelField {}
 Field of each options row shown to the user (x-optionLabel); set with optionsAction.

Detailed Description

Per-field presentation overrides and scalar bounds: label, help, placeholder, read-only, hidden, minimum/maximum/multipleOf, and a plain member's display unit/decimals (docs/spec/forms/forms.md, "Field metadata").

An action opts in with a static constexpr std::array<FieldMeta, N> (or, for the describe<>() sugar, a static const array defined out-of-line — see describe()'s documentation) named fieldMetadata, mirroring the existing optionalFields convention. Every member other than field defaults to "not declared": an empty label/help/ placeholder means "infer the title, omit the rest"; readOnly/hidden default to false; a disengaged minimum/maximum/multipleOf emits nothing and checks nothing; an empty unit and a disengaged decimals emit nothing. mergeSchemaExtras looks up the entry (if any) matching each reflected member by wire key and patches the property node; an entry naming a field that does not exist on the action is ignored.

Bounds are per field, and are not presentation
The three numeric members are the one part of this type that is not presentation: morph::forms::allFieldBoundsSatisfied evaluates them as a C++ predicate, so an action whose validate() calls it enforces the same declaration the schema advertises — the "the DTO *is* the form definition" rule (examples/IMPLEMENTATION.md rule 3) applied to a scalar bound, which the formRules vocabulary cannot express because every comparison node there takes two member pointers, never a literal. They are keyed by field rather than by unit precisely so a floor declared for one Quantity member does not constrain a sibling of the same type — UnitTraits::bounds is per-unit and cannot make that distinction.

Definition at line 225 of file forms.hpp.

Member Function Documentation

◆ withPlaceholder()

FieldMeta morph::forms::FieldMeta::withPlaceholder ( std::string_view text) const
inlinenodiscardconstexprnoexcept

Returns a copy with placeholder set to text.

Parameters
textThe placeholder hint.
Returns
The updated descriptor.

Definition at line 344 of file forms.hpp.

◆ withReadOnly()

FieldMeta morph::forms::FieldMeta::withReadOnly ( ) const
inlinenodiscardconstexprnoexcept

Returns a copy with readOnly set to true.

Returns
The updated descriptor.

Definition at line 352 of file forms.hpp.

◆ withHidden()

FieldMeta morph::forms::FieldMeta::withHidden ( ) const
inlinenodiscardconstexprnoexcept

Returns a copy with hidden set to true.

Returns
The updated descriptor.

Definition at line 360 of file forms.hpp.

◆ withMinimum()

FieldMeta morph::forms::FieldMeta::withMinimum ( ::morph::math::Rational bound) const
inlinenodiscardconstexprnoexcept

Returns a copy with minimum set to bound.

Parameters
boundInclusive lower bound, in the field's canonical unit.
Returns
The updated descriptor.

Definition at line 369 of file forms.hpp.

◆ withMaximum()

FieldMeta morph::forms::FieldMeta::withMaximum ( ::morph::math::Rational bound) const
inlinenodiscardconstexprnoexcept

Returns a copy with maximum set to bound.

Parameters
boundInclusive upper bound, in the field's canonical unit.
Returns
The updated descriptor.

Definition at line 378 of file forms.hpp.

◆ withMultipleOf()

FieldMeta morph::forms::FieldMeta::withMultipleOf ( ::morph::math::Rational step) const
inlinenodiscardconstexprnoexcept

Returns a copy with multipleOf set to step.

Parameters
stepDivisor the value must be an exact integer multiple of; non-positive values are ignored (see the member).
Returns
The updated descriptor.

Definition at line 388 of file forms.hpp.

◆ withUnit()

FieldMeta morph::forms::FieldMeta::withUnit ( std::string_view text) const
inlinenodiscardconstexprnoexcept

Returns a copy with unit set to text.

Parameters
textThe display unit, e.g. "kg/m³".
Returns
The updated descriptor.

Definition at line 397 of file forms.hpp.

◆ withDecimals()

FieldMeta morph::forms::FieldMeta::withDecimals ( ::morph::math::DecimalPlaces places) const
inlinenodiscardconstexprnoexcept

Returns a copy with decimals set to places.

Parameters
placesFraction digits to display and accept.
Returns
The updated descriptor.

Definition at line 406 of file forms.hpp.

◆ withBlankAs()

FieldMeta morph::forms::FieldMeta::withBlankAs ( BlankAs mode) const
inlinenodiscardconstexprnoexcept

Returns a copy with blankAs set to mode.

Parameters
modeWhat a blank control submits.
Returns
The updated descriptor.

Definition at line 415 of file forms.hpp.

Member Data Documentation

◆ field

std::string_view morph::forms::FieldMeta::field

Wire key of the member this entry describes.

Definition at line 227 of file forms.hpp.

◆ label

std::string_view morph::forms::FieldMeta::label {}

Display label; empty infers a title-cased name from field.

Definition at line 229 of file forms.hpp.

◆ help

std::string_view morph::forms::FieldMeta::help {}

Help text; empty omits description.

Definition at line 231 of file forms.hpp.

◆ placeholder

std::string_view morph::forms::FieldMeta::placeholder {}

In-control placeholder hint; empty omits x-placeholder.

Definition at line 233 of file forms.hpp.

◆ i18nKey

std::string_view morph::forms::FieldMeta::i18nKey {}

Explicit message-key stem override for this field's i18n catalog keys; empty means "derive the stem from the action's `ActionTraits<A>::typeId()` and this field's wire key" (see morph::forms::i18n::fieldKey, forms/i18n.hpp). A non-empty stem replaces only the <actionTypeId>.<wireField> portion of the key — the per-slot .label / .help / .placeholder suffix is still appended on top of it (see morph::forms::i18n::explicitFieldKey), so "myKey" expands to "myKey.label" / "myKey.help" / "myKey.placeholder", never to a single complete key on its own. Emitted as x-i18nKey only when non-empty.

Definition at line 245 of file forms.hpp.

◆ widget

std::string_view morph::forms::FieldMeta::widget {}

Widget-selection override; empty means "use the field type's own `widget()`, if any". A non-empty value replaces that type-derived default and is emitted as x-widget (docs/spec/forms/widget_hints.md). Read structurally by detail::widgetOverride, not through this type by name — see detail::HasFieldMetadataWidgets.

Definition at line 252 of file forms.hpp.

◆ readOnly

bool morph::forms::FieldMeta::readOnly {false}

Displayed but not editable when true; emits x-readonly.

Definition at line 254 of file forms.hpp.

◆ hidden

bool morph::forms::FieldMeta::hidden {false}

Not shown at all when true; emits x-hidden. The field still travels in the payload (see docs/spec/forms/forms.md, "Field metadata is not a security control").

Definition at line 258 of file forms.hpp.

◆ minimum

std::optional<::morph::math::Rational> morph::forms::FieldMeta::minimum {}

Inclusive lower bound on the field's numeric value; emitted as the standard JSON-Schema minimum. Disengaged means "no floor".

For a Quantity member this bounds the scalar value the field denotes, in the canonical unit — not the {num,den,dp} object the member serialises as.

Definition at line 266 of file forms.hpp.

◆ maximum

std::optional<::morph::math::Rational> morph::forms::FieldMeta::maximum {}

Inclusive upper bound on the field's numeric value; emitted as the standard JSON-Schema maximum. Disengaged means "no ceiling". Same canonical-unit reading as minimum.

Definition at line 271 of file forms.hpp.

◆ multipleOf

std::optional<::morph::math::Rational> morph::forms::FieldMeta::multipleOf {}

The field's value must be an exact integer multiple of this; emitted as the standard JSON-Schema multipleOf. Disengaged means "any value".

multipleOf = 1 is how integrality is spelled — the constraint Quantity cannot carry in its type, since Quantity<U, Dec> requires Dec >= 1 and therefore always represents tenths exactly.

A non-positive value is ignored (neither emitted nor checked), matching JSON Schema, which requires multipleOf to be strictly positive: a zero divisor has no meaning and a negative one divides exactly the same set of values as its magnitude.

Definition at line 285 of file forms.hpp.

◆ unit

std::string_view morph::forms::FieldMeta::unit {}

Display unit for a member whose C++ type carries none (a plain double, float or integral member); emitted as the property's ExtUnits ({"unitAscii": unit, "unitUnicode": unit}), the key a Quantity already carries. Empty emits nothing.

Presentation only: the unit never travels in the payload and nothing converts through it. Ignored on a Quantity member, whose unit is part of its type and already emitted.

Definition at line 298 of file forms.hpp.

◆ decimals

std::optional<::morph::math::DecimalPlaces> morph::forms::FieldMeta::decimals {}

Display and entry precision: for a plain double/float member emitted as x-displayDecimals, for a bare math::Rational member as x-decimalPlaces. Disengaged emits nothing.

A double gets x-displayDecimals, not x-decimalPlaces: the latter hands a property the exact {num,den,dp} encoding, which a double cannot decode, while the former keeps the plain JSON-number encoding and only tells a renderer how many fraction digits to show and accept. A Rational already travels as {num,den,dp}, so it gets x-decimalPlaces and is entered as one decimal number at those places rather than as three integers. Ignored on a Quantity member (its x-decimalPlaces is authoritative) and when it exceeds morph::math::kMaxDecimalPlaces.

Definition at line 314 of file forms.hpp.

◆ blankAs

BlankAs morph::forms::FieldMeta::blankAs {BlankAs::Omit}

What a blank control submits for a std::string / std::optional<std::string> member; BlankAs::Empty emits "x-blankAs": "empty".

An edit form prefilled from a stored record cannot otherwise clear an optional string: a blank control is omitted, and an omitted member reads as "leave it unchanged". With Empty a field the user emptied – or one prefilled with "" – submits ""; a field never prefilled and never typed into is still omitted. Ignored on any other member type.

Definition at line 326 of file forms.hpp.

◆ optionsAction

std::string_view morph::forms::FieldMeta::optionsAction {}

Type id of the registered action whose result rows are this member's options, for a member that is not a Choice<…>: the member is emitted with x-optionsAction, x-optionValue and x-optionLabel, as a Choice is, so a renderer draws it as a lookup select. Empty emits nothing. Set together with valueField and labelField; a Choice member, whose type already names its options, refuses it.

Definition at line 333 of file forms.hpp.

◆ valueField

std::string_view morph::forms::FieldMeta::valueField {}

Field of each options row submitted as the value (x-optionValue); set with optionsAction.

Definition at line 336 of file forms.hpp.

◆ labelField

std::string_view morph::forms::FieldMeta::labelField {}

Field of each options row shown to the user (x-optionLabel); set with optionsAction.

Definition at line 339 of file forms.hpp.


The documentation for this struct was generated from the following file: