ArrayBlock
Defined in: projects/ngx-signal-schema/src/lib/structure/array-block.ts:152
ArrayBlock – Purpose and Usage
Section titled “ArrayBlock – Purpose and Usage”Why this exists
Section titled “Why this exists”Deprecated
Section titled “Deprecated”since Angular v22. most use cases can be solved by using plain raw arrays.
ArrayBlock<T> is a lightweight wrapper around a plain array that enables type-safe and explicit control over array-level form state in Angular Signal Forms.
While Angular Signal Forms natively support raw arrays (e.g. T[]), ArrayBlock<T> provides several advantages for developer experience and structural clarity:
- Type-safe addressability: Items within a raw array are not natively exposed with numeric index signatures in the
FieldTreeorSchemaPathtypes.ArrayBlock<T>provides a nameditemsproperty that is fully typed, allowing you to accessform.items[0]orpath.items[0]without type casting. - Explicit Container Node: It introduces a dedicated container node for the collection itself. This is especially useful for attaching collection-level validation errors (e.g., “minimum 3 items”) to a stable, addressable path (
items) rather than the array root. - Consistent API Surface: By using an object wrapper, you ensure that the collection behaves exactly like other object-based form nodes, making state propagation and conditional logic more predictable in complex schemas.
ArrayBlock<T> solves this by introducing a dedicated container node with a named items property.
What problem it solves
Section titled “What problem it solves”Without ArrayBlock<T>:
schema<string[]>(ctx => { readonly(ctx); // ✅ Marks the array as readonly and propagates to items // ⚠️ But index access is not type-safe: (myForm as any)[0]
validate(ctx, items => items.length > 0 ? null : { minLength: true }); // ✅ Validation runs and error exists in summary // ⚠️ But attaching errors to a stable path for the UI is more manual});With ArrayBlock<T>:
schema<ArrayBlock<string>>(ctx => { readonly(ctx); // ✅ Works perfectly // ✅ Item fields are fully addressable: myForm.items[0]});This allows you to:
- Type-safe access to items via
items[0]on both the form and schema path - Explicit collection state (readonly, disabled) with clear structural intent
- Easier UI binding for collection-level errors via the stable
itemspath - Predictable behavior for complex nested forms
Design goals
Section titled “Design goals”-
No parallel state model Keeps all state inside the Signal Forms system (no external
lockedflags needed) -
Minimal abstraction Adds only a thin wrapper without changing the semantics of your data
-
Composable Works seamlessly with existing patterns like
OptionalBlock<T> -
Non-invasive Can be introduced only where needed (e.g. for specific form fields)
Interface definition
Section titled “Interface definition”export interface ArrayBlock<T> { items: T[];}Mapping helpers
Section titled “Mapping helpers”function toArrayBlock<T>(items: T[]): ArrayBlock<T> { return { items };}
function fromArrayBlock<T>(arrayBlock: ArrayBlock<T>): T[] { return arrayBlock.items;}These functions allow you to:
- Convert incoming DTOs into a form-compatible structure
- Convert back to the original shape when persisting data
Example in a form schema
Section titled “Example in a form schema”const schema = schema<ArrayBlock<Datei>>(ctx => { readonly(ctx); // locks the entire array
applyEach(ctx.items, item => { readonly(item.id); readonly(item.originalName); });});When to use it
Section titled “When to use it”Use ArrayBlock<T> when:
- You want type-safe access to individual items (e.g.
form.items[0]) withoutas any - You need to apply schema rules to specific indices in a typed way
- You have complex collection-level validation that should be bound to a named UI path
- You want to maintain a strict, object-oriented form structure
Do not use it if:
- You are working with a simple list of values and don’t need typed index access
- You prefer the cleanest possible JSON model and handle item-level logic via iteration (e.g.
@for)
Conceptual summary
Section titled “Conceptual summary”ArrayBlock<T> is not a domain model construct.
It is a form modeling tool that bridges a gap in how Signal Forms handle arrays.
It turns this:
T[]into this:
{ items: T[] }so that the array becomes a first-class form node with its own stable, addressable path.
Type Parameters
Section titled “Type Parameters”T
Properties
Section titled “Properties”items:
T[]
Defined in: projects/ngx-signal-schema/src/lib/structure/array-block.ts:153