Skip to content

Forms with FormObjectBase

Drupal\formfactorykits\Form\FormObjectBase (src/Form/FormObjectBase.php) extends Drupal core's FormBase. It injects the formfactory and formfactorykits services and turns buildForm() into a call to your buildFormObject() method.

You implement Called from Arguments
getFormId() Form API (none)
buildFormObject() (required, from FormObjectInterface) buildForm() FormFactoryInterface $form_factory, FormFactoryKitsInterface $kits
validateFormObject() (optional) validateForm(), only if the method exists same as above
submitFormObject() (optional) submitForm(), only if the method exists same as above

buildForm() loads the incoming $form and $form_state into the form factory, calls buildFormObject(), and returns $form_factory->getForm(). The form state is available as $form_factory->getFormState().

<?php

namespace Drupal\example\Form;

use Drupal\formfactory\Services\FormFactoryInterface;
use Drupal\formfactorykits\Form\FormObjectBase;
use Drupal\formfactorykits\Services\FormFactoryKitsInterface;

class ExampleForm extends FormObjectBase {

  public function getFormId() {
    return 'example_form';
  }

  public function buildFormObject(FormFactoryInterface $form_factory, FormFactoryKitsInterface $kits): void {
    // Optional: the form state is available through the form factory.
    $form_state = $form_factory->getFormState();

    // Vertical tabs with a "dogs" tab.
    $tabs = $kits->verticalTabs();
    $form_factory->append($tabs);

    $tabs->createTab('dogs')
      ->setTitle($this->t('Dogs'))
      ->append(
        $kits->textArea('dogs_description')
          ->setTitle($this->t('Description'))
      )
      ->append(
        $kits->checkboxes('dogs_attributes')
          ->setTitle($this->t('Attributes'))
          ->appendOption(['a' => $this->t('A')])
          ->appendOption(['b' => $this->t('B')])
          ->setDefaultValue(['b'])
      );

    $form_factory->append($kits->submit());
  }

  public function submitFormObject(FormFactoryInterface $form_factory, FormFactoryKitsInterface $kits): void {
    $values = $form_factory->getFormState()->getValues();
    $this->messenger()->addStatus($this->t('Saved.'));
  }

}

The array that buildForm() returns for this class is:

[
  'vertical_tabs' => [
    '#parents' => ['vertical_tabs'],
    '#type' => 'vertical_tabs',
  ],
  'dogs' => [
    '#type' => 'details',
    '#title' => 'Dogs',
    '#group' => 'vertical_tabs',
    'dogs_description' => [
      '#type' => 'textarea',
      '#title' => 'Description',
    ],
    'dogs_attributes' => [
      '#type' => 'checkboxes',
      '#title' => 'Attributes',
      '#default_value' => ['b'],
      '#options' => ['a' => 'A', 'b' => 'B'],
    ],
  ],
  'submit' => [
    '#value' => t('Submit'),   // TranslatableMarkup
    '#type' => 'submit',
    '#button_type' => 'primary',
  ],
]

Notes

  • validateFormObject() and submitFormObject() are not part of FormObjectInterface. FormObjectBase finds them with method_exists(), so a typo in the name means the method is silently not called.
  • FormObjectBase does not stop you from overriding validateForm() or submitForm() yourself. If you do, the *FormObject() methods are no longer called unless you call parent::.
  • To keep using core's FormBase instead, use the pattern from Altering any $form array inside your buildForm().