Skip to content

Altering any $form array

The shortest way to use kits is to load an existing $form array into a FormFactory, append kits, and read the array back. This works anywhere you hold a $form: in buildForm(), in hook_form_alter(), or in a form #process callback.

/** @var \Drupal\formfactory\Services\FormFactoryInterface $form_factory */
$form_factory = \Drupal::service('formfactory')->load($form);
/** @var \Drupal\formfactorykits\Services\FormFactoryKitsInterface $kits */
$kits = \Drupal::service('formfactorykits');

// A `textfield` element.
$form_factory->append(
  $kits->textField('nickname')
    ->setTitle('Nickname')
    ->setMaxLength(32)
);

// A `select` element.
$form_factory->append(
  $kits->select('color')
    ->setTitle('Favourite color')
    ->setOptions(['red' => 'Red', 'blue' => 'Blue'])
);

// A `submit` button. Its default label is "Submit".
$form_factory->append($kits->submit());

// Build the render array.
$form = $form_factory->getForm();

getForm() returns the original $form with one new key per appended kit (nickname, color, submit). Existing keys in $form stay as they were, unless a kit uses the same ID, in which case the kit's array replaces the existing element.

In hook_form_alter()

function mymodule_form_user_login_form_alter(array &$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form_factory = \Drupal::service('formfactory')->load($form, $form_state);
  $kits = \Drupal::service('formfactorykits');

  $form_factory->append(
    $kits->markup('login_help')
      ->setMarkup('<p>Use your work email address.</p>')
  );

  $form = $form_factory->getForm();
}

Things to know

  • text() is markup, not a text field. $kits->text() returns a TextKit, which renders #type => 'markup' and strips tags from the value you give to setValue(). Use $kits->textField() for a textfield input.
  • file() currently fails. FormFactoryKitsService::file() calls FileKit::create() without importing that class, so it throws Error: Class "Drupal\formfactorykits\Services\FileKit" not found. Until it is fixed, create a managed file kit directly: \Drupal\formfactorykits\Kits\Field\Media\ManagedFile\FileKit::create($kits, 'upload'), or use $kits->image() for images.
  • The formfactory service is shared. FormFactoryService keeps its list of appended kits between calls to load(). Use one load() → append() → getForm() sequence per form build.
  • Titles are stored as strings. setTitle() and setDescription() take a string. Passing $this->t('...') works in files without declare(strict_types=1), but the TranslatableMarkup is converted to a string at that point. In a file with strict_types=1, cast it yourself: ->setTitle((string) $this->t('Name')). Values passed through the $parameters argument of a factory method (for example $kits->textField('name', ['title' => $this->t('Name')])) are stored as given.