Children
Declared occupants of slots, including owner-aware factories for live parent-to-child bindings.
A child declaration names the occupant of a slot. The field name selects the slot.
class Phone extends LayoutActor<typeof phoneSlots> {
static slots = phoneSlots;
statusBar = child(StatusBar); // occupies the "statusBar" slot
app = child(MailApp); // occupies the "app" slot
}Static overrides
Pass an overrides object for fixed initial state:
statusBar = child(StatusBar, { carrier: "MotionActor", batteryPct: 82 });Owner-dependent overrides
Pass a factory instead when the child's inputs depend on the parent. The derived
values continue to read the owner during resolution, so the binding stays live rather than
being a one-time copy at spawn.
class Row extends LayoutActor<typeof rowSlots> {
static slots = rowSlots;
label = child(TextBlock, (owner: Row) => ({
content: derived(() => owner.title()),
layout: { width: derived(() => owner.layout.width()) },
}));
}This is the form people miss
The instinct is to drop into onSpawn() and wire the child by hand. Don't — an
owner-aware factory keeps the child a declared field, keeps the binding live, and keeps
the structure visible to the type system. Save onSpawn() for children that are
genuinely conditional.
Dynamic children
Use hostInSlot(...), optionally in onSpawn(),
when children are conditional or data-driven:
onSpawn() {
if (this.showToolbar()) {
this.hostInSlot("chrome", Toolbar);
}
}Reading a child
A declared child is a typed field, so it reads like any other property — and it can be returned as a scene export:
return { card, caption: card.caption };const { caption } = compiled.at(frame).scene;
caption.text; // typed