Skip to content

has-many

A repeater whose visible submitted rows are authoritative for one Lucid has-many relation. Omission is handled by the fill set and performs no write.

Builder F.hasMany(relation: string, schema: readonly SchemaComponent[] = []): HasMany
Wire type key has-many
Class chain HasManyRepeaterField
Detail projection repeater-entry
Column counterpart (not tabulatable)

Example

import { F } from '@adonia/core'

F.hasMany('attribute')

Props

Beyond the shared field DSL:

Prop Declared on Behaviour
relation(name: string): this HasMany Changes the parent model relation used for hydration, scope, and persistence.
keyType(type: 'number' | 'string'): this HasMany Selects the Vine/ownership id type accepted in submitted child rows.
min(count: number): this Repeater Minimum number of rows; compiles to the array’s minLength (§11.1).
max(count: number): this Repeater Maximum number of rows; compiles to the array’s maxLength (§11.1).
reorderable(): this Repeater Lets the user drag rows into a new order (order is the array order).
collapsible(): this Repeater Lets the user fold individual rows away.
itemLabel(source: string | ItemLabelFn): this Repeater Names each row.
table(): this Repeater Compact layout: rows render as table lines rather than stacked cards. A rendering hint only — the state shape and the validator are identical either way.
defaultItems(count: number): this Repeater Pre-populates count blank rows in create mode (protocol §7): the node’s default becomes an array of Repeater.blankItems, so a form that always has at least one row does not make the user press “add” first.

Introspection

Read-only members this type adds — used by the compiler, the table derivation and tests rather than by a schema author.

Member Declared on Behaviour
boundaryKeys(): readonly string[] HasMany Preserves child identity and lock snapshots across nested validation.
contributeHints(hints: EagerHints): void HasMany Preloads the declared relation once so hydration never becomes per-row I/O.
detailProps(): JsonObject HasMany Carries the resolved relation name into the detail projection.
hydrateOptimisticLocks( record: unknown, value: unknown, ctx: HttpContextLike ): Promise<void> HasMany Adds the child resource’s lock snapshot after ordinary synchronous form hydration. Resource lookup is lazy and therefore must happen in this explicit asynchronous pass.
persistRelation(record: object, value: unknown, ctx: HttpContextLike): Promise<void> HasMany Reconciles the submitted rows against children owned by the active parent.
nestedSchema(): readonly SchemaComponent[] Repeater The item sub-form (protocol §2 children of this node). Declared here rather than as a LayoutComponent’s children because this is a STATE boundary: the descriptor compiler emits the sub-form as children but stops collecting stateKeys, and collectFields never descends.
blankItem(): RepeaterItem Repeater A fresh empty row: every child key present, holding its declared default or explicit null.
labelFor(item: RepeaterItem, index: number): string Repeater The human name of one row, server-side: the itemLabel closure when declared, otherwise the named child key’s value, otherwise the ordinal.

Validation

Vine base: vine.string(), vine.number().

Contributed by HasMany.vineSchema() in packages/core/src/schema/fields/has_many.ts. The shared modifiers (required, nullable, requiredWhen, unique, optionality) are applied on top by Field.buildValidation, and a rules() override replaces the base entirely — the validator compiler never branches on the field class.

Declared in

  • packages/core/src/schema/fields/has_many.tsHasMany
  • packages/core/src/schema/fields/repeater.tsRepeater
Navigation

Type to search…

↑↓ navigate↵ selectEsc close