I have the following routes in module_name.routing.yml.

  path: 'module_name/usergroup/delete/{arg1}'
    _form: '\Drupal\module_name\Form\DeleteUserGroup'
    _title: 'Delete User group'
    _permission: 'access admin menus'

This is the code in module_name/src/Form/DeleteUserGroup.php.

namespace Drupal\module_name\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

class DeleteUserGroup extends ConfigFormBase {

  public function getFormId() {
    return 'delete_user_group';
 * General form for switching all nodes from one user to another.
  public function buildForm(array $form, FormStateInterface $form_state,$product_code) {
  $form['_product'] = array(
        '#type' => 'value',
        '#value' => $product_code,);
//get the user group and username to display the confirmation message 
$result = db_query('select field_p_group_name_value from {content_type_usergroup} ctu'       
        . ' where vid=%d',$product_code);      
    while ($row = $result->fetchObject()) {
      $user_group = $row->field_p_group_name_value;

return confirm_form($form,t('Are you sure you want to delete "' .$user_group. '" User Group?'),
        isset($_GET['destination']) ? $_GET['destination'] : "function_name",t('This action cannot be undone.'),t('Delete'),t('Cancel'));

 * #submit callback for node_adoption_transfer_form().
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();
  //if ($form_state['values']['confirm']) {
    $param = $form_state->getValue('_product');
    drupal_set_message(t('Group ' .$param.' will get deleted.'));               
    db_query('DELETE FROM {content_type_usergroup} WHERE vid = %d', $param);
    //delete the users of the usergroup too
    db_query('DELETE FROM {usergroup_user_map} WHERE group_id=%d', $param);
    drupal_set_message(t('usergroup has been deleted.'));

  protected function getEditableConfigNames() {
    return "delete_user_group";


I am getting the following error:

DeleteUserGroup::buildForm() must be compatible with Drupal\Core\Form\FormInterface::buildForm(array $form, Drupal\Core\Form\FormStateInterface $form_state)


  • Can anyone explain how this equates when using the WebForm module? I have no module specifically for the form I have built using the module, so what would the point '_form' to within the routing.yml file ?
    – John Cogan
    Commented Nov 6, 2017 at 13:40

3 Answers 3


The parameter has to have the same name in routing.yml and build method. And when using parameters in forms you have to set a null value in the parameter list:

public function buildForm(array $form, FormStateInterface $form_state, $arg1 = NULL) {
  • 4
    Ah yes! The additional parameters always have to be NULL to be compatible with Drupal\Core\Form\FormInterface::buildForm.💡
    – leymannx
    Commented Mar 17, 2020 at 22:13
  • @leymannx I would be even concrete that additional parameters should be optional (nullable) with defaults like NULL, 'some_string', '2' and so on. See for example core/modules/comment/src/Form/CommentAdminOverview.php BTW: it is true for any method that follows interface where you want to add extra parameters. Commented Feb 28, 2021 at 15:09
  • Is this and second highest rated answer still valid (D9/D10)? It seems to me you explicitly need to state the parameter under defaults in the routing.yml and it's been put to '' instead of NULL (in form class too). Like can be seen: git.drupalcode.org/project/drupal/-/blob/… and git.drupalcode.org/project/drupal/-/blob/… Commented Mar 20, 2023 at 12:07
  • Ah okay, seems to depend on form class from which you derive, ConfigFormBase seems to require the param in the defaults in routing.yml, while just FormBase does not. That said, not sure why the BanAdmin Route uses this, seems not necessary. Commented Mar 20, 2023 at 12:22

First create a routing.yml file

  path: '/example_module/form/{arg}'
    _form: '\Drupal\example_module\Form\ExampleForm'
    _permission: 'access content'

Then create a .php file under folder structure /src/Form/ExampleForm.php. Then build a form

public function buildForm(array $form, FormStateInterface $form_state, $arg = NULL) {
  $form['example_note'] = [
    '#type' => 'textarea',
    '#title' => $this->t('Block contents'),
    '#description' => $this->t('This text will appear in the example block.'),
    '#default_value' => $arg,
  $form['actions'] = ['#type' => 'actions'];
  $form['actions']['delete'] = [
    '#type' => 'submit',
    '#value' => $this->t('Delete'),
  return $form;
  • default arg: should be passed in route definition. Commented Aug 1, 2023 at 8:44

This is not asked in the question. Maybe it could also help, I had to pass a parameter to a form that was not loaded by a route. The form is integrated into a template loaded by a controller.

In custom_module.routing.yml:

path: '/lorem/{arg}'
    _controller: '\Drupal\my_module\Controller\LoremController::testLorem'

In the controller, the form is called and the parameter $arg is passed to the form builder.

public function testLorem($arg) {
     $form = \Drupal::formBuilder()->getForm('Drupal\my_module\Form\testForm', $arg);
     $build = [
         '#theme' => 'custom_theme',
         '#form' => $form,
         '#arg' => $arg,

     return $build;

And in the form :

public function buildForm(array $form, FormStateInterface   $form_state, $arg = null) {
  • 1
    I came here looking for exactly this. Thank you! Commented Feb 10, 2023 at 1:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.