/

Nested Tables Overview

Embedding a child table's rows inside a parent record's edit form with nested_table() - the shared XcrudNested API, and the five layouts a nested table can render in.

nested_table()

Call nested_table() on an Xcrud instance to embed a child table's rows inside the parent's edit form:

public function nested_table(
    string $label,
    string $parentField,
    string $childTable,
    string $childField,
    ?int $order = null
): XcrudNested
ParameterTypeDefaultDescription
$labelstringrequiredLabel shown for this nested table (tab name, section heading, etc., depending on position)
$parentFieldstringrequiredColumn on the parent table whose value filters the child rows
$childTablestringrequiredThe child table to embed (must be whitelisted)
$childFieldstringrequiredColumn on the child table compared against $parentField's value
$order?intnullPosition among sibling nested tables/the parent's own fields tab; omitted falls back to declaration order

It returns an XcrudNested node - a mini CRUD grid ($childTable rows WHERE $childField = the parent row's own $parentField value) with its own Add/Edit/Delete. XcrudNested is a deliberate subset of Xcrud: no search box, no advanced-filter panel, no bulk actions, no sum(), no group_by_columns() at the nested level. What it does keep is enough to call nested_table() on the returned node again, nesting arbitrarily deep - a nested table can itself have further nested tables, each level getting the same treatment.

$xcrud = Xcrud::get_instance();
$xcrud->table('orders');
$xcrud->route('orders');

$orderdetails = $xcrud->nested_table('Order details', 'orderNumber', 'orderdetails', 'orderNumber');
$orderdetails->columns('productCode,quantityOrdered,priceEach');
$orderdetails->order_by('productCode', 'asc');

echo $xcrud->render();

The XcrudNested API

The most commonly used methods on a returned node:

MethodDescription
columns($fieldList)Restricts/orders which of the child table's whitelisted columns the nested grid shows
fields($fieldList)Restricts/orders which editable columns the nested grid's own Add/Edit form shows
order_by($field, $dir = 'asc')Sort order for the nested grid's rows
limit($n)Page size for the nested grid; default 100
relation(...)Foreign-key dropdown for a nested field, same shape as the top-level relation()
gallery($field, $childTable, $options)Multi-image field on the nested grid's own Add/Edit form
highlight() / highlight_row()Conditional cell/row styling, same as the top-level methods
intelligent_column_fit($enabled = true)Per-node override of the responsive column-fit behavior
default_tab($label, $order = null)Labels/orders the tab that holds this node's OWN row fields, once it has nested_table() children of its own

position() - where it renders

position($position = 'bottom') is the key layout control - it decides where a nested table shows up in its parent's edit form:

public function position(string $position = 'bottom'): self
ValueDescription
tabDefault. Behind its own tab, alongside the parent's own fields tab
bottomAlways-visible, full-width section appended directly below the parent's own fields
bottom-fixedSame as bottom, but sticky/pinned near the bottom of the panel, with a draggable resize handle and its own internal scroll (~35% height by default)
left / rightA fixed-width sticky sidebar column alongside the parent's own fields, with a draggable width

Only where a node renders changes - what it does once visible (columns, fields, relations, further nesting) stays identical regardless of position.