Skip to content

Nesting

Any kit can hold child kits: call append($kit) on the parent. When the parent builds its array, each child's array is added under the child's ID. This page shows the container kits that are meant for nesting and the exact arrays they produce.

Details

$details = $kits->details('outer')
  ->setTitle('Outer')
  ->setOpen();
$details->append($kits->textField('a')->setTitle('A'));
$form_factory->append($details);
'outer' => [
  '#type' => 'details',
  '#title' => 'Outer',
  '#open' => TRUE,
  'a' => [
    '#parents' => ['outer'],
    '#type' => 'textfield',
    '#title' => 'A',
    '#group' => 'outer',
  ],
],

#parents on nested children

The child's #parents contains the ancestor IDs only (['outer']), not the child's own key. Form API stores a submitted value at the path given by #parents, so check the submitted values of fields nested in a DetailsKit (two children with the same ancestors share that path). No test in this repository covers form submission of nested kits.

Containers

ContainerKit does not pass its ID down as a parent, so its children get no #parents. They still get #group.

$form_factory->append(
  $kits->container('results')
    ->wrap()
    ->append($kits->markup('msg')->setMarkup('<p>Hi</p>'))
);
'results' => [
  '#type' => 'container',
  '#prefix' => '<div id="results-wrapper">',
  '#suffix' => '</div>',
  'msg' => [
    '#type' => 'markup',
    '#markup' => '<p>Hi</p>',
    '#group' => 'results',
  ],
],

wrap() (from WrapTrait) puts a <div> with the ID <kit id>-wrapper around the element, which is a convenient AJAX target. Pass an ID to wrap('my-id') to choose it.

Vertical tabs

VerticalTabsKit groups its children: FormFactory::getForm() places each tab next to the vertical tabs element (at the same level), not inside it. Each tab is a TabKit (a details element) whose #group points at the tabs.

$tabs = $kits->verticalTabs();
$form_factory->append($tabs);

$tabs->createTab('dogs')
  ->setTitle('Dogs')
  ->append($kits->textArea('dogs_description')->setTitle('Description'));
$tabs->createTab('cats')
  ->setTitle('Cats');
'vertical_tabs' => [
  '#parents' => ['vertical_tabs'],
  '#type' => 'vertical_tabs',
],
'dogs' => [
  '#type' => 'details',
  '#title' => 'Dogs',
  '#group' => 'vertical_tabs',
  'dogs_description' => [
    '#type' => 'textarea',
    '#title' => 'Description',
  ],
],
'cats' => [
  '#type' => 'details',
  '#title' => 'Cats',
  '#group' => 'vertical_tabs',
],

createTab() returns the new TabKit, so you can chain setTitle() and append() on it. setDefaultTab('dogs') sets #default_tab to edit-dogs. Children of a tab do not get #parents or #group.

Tables

TableKit renders a table element from header columns and rows of cells. Rows are plain arrays (or TableRowKit objects).

$form_factory->append(
  $kits->table('people')
    ->setCaption('People')
    ->appendHeaderColumn('Name')
    ->appendHeaderColumn('Role')
    ->appendRow(['Ada', 'Admin'])
    ->appendRow(['Bob', 'Editor'])
    ->setSticky()
);
'people' => [
  '#type' => 'table',
  '#caption' => 'People',
  '#header' => ['Name', 'Role'],
  '#sticky' => TRUE,
  '#rows' => [
    ['Ada', 'Admin'],
    ['Bob', 'Editor'],
  ],
],

For a table of selectable rows, use TableSelectKit ($kits->tableSelect()); see the field kit reference.

Build once

Building a nested tree adds the parent ID to each child's context as a side effect, so building the same kit objects twice repeats IDs in #parents. Create the kits, call getForm() once, and discard them.