Using the same form more than once per page with AJAX callbacks I have a small email signup form made from extending FormBase that takes an email address and submits it to a mail service. I need to change the submit to AJAX so I can flash a success or error message.

I want to show this form more than once on a page. Once in a CTA near the top of the page, and there is a slightly different styled version in the footer.

When I added #ajax to the submit button, only one instance of the form seems to be affected. Here is the whole form:

$info = $form_state-&gt;getBuildInfo();

$form['#prefix'] = '&lt;section class="hl__single-input-form"&gt;';
$form['#suffix'] = '&lt;/section&gt;';
$form['#attributes']['class'][] = 'hl__single-input-form__form';

$form['title'] = [
  '#type' =&gt; 'label',
  '#for' =&gt; 'edit-email-address',
  '#title' =&gt; 'Stay in the know',
  '#attributes' =&gt; [
    'class' =&gt; [
      'hl__label',
      'hl__label--inline',
    ],
  ],
];

if (!empty($info['args'][0]) &amp;&amp; $info['args'][0] == "show_tagline") {
  $form['tagline'] = [
    '#markup' =&gt; '&lt;div class="hl__single-input-form__helper-text"&gt;Sign up for email updates from MySite&lt;/div&gt;',
  ];
}

$form['email_address'] = [
  '#type' =&gt; 'email',
  '#size' =&gt; NULL,
  '#required' =&gt; TRUE,
  '#attributes' =&gt; [
    'placeholder' =&gt; $this-&gt;t('Email'),
    'class' =&gt; [
      'hl__input',
      'hl__input--inline',
      'js-is-required',
    ],
    'data-twig-suggestion' =&gt; 'newsletter_signup_email',
  ],
  '#prefix' =&gt; '&lt;div class="hl__single-input-form__input-group"&gt;',
];

$form['submit'] = [
  '#type' =&gt; 'submit',
  '#value' =&gt; $this-&gt;t('Sign up'),
  '#attributes' =&gt; [
    'class' =&gt; [
      'hl__button',
      'hl__button--small',
      'hl__button--inline',
    ],
    'data-twig-suggestion' =&gt; 'newsletter_signup_submit',
  ],
  '#suffix' =&gt; '&lt;/div&gt;',
  '#ajax' =&gt; [
    'wrapper' =&gt; 'hl__single-input-form',
  ]
];


The block in the footer that pulls the form just has this build method:

  /**
   * {@inheritdoc}
   */
  public function build() {
    return ['form' =&gt; $this-&gt;formBuilder-&gt;getForm('\Drupal\harlib_newsletter_signup\Form\NewsletterSignup')];
  }


The preprocess for the Paragraph that outputs the form when being themed:

$variables['signup_form'] = \Drupal::service('form_builder')-&gt;getForm('\Drupal\harlib_newsletter_signup\Form\NewsletterSignup', "show_tagline");


How can I support having this form on the page more than once, both with the same AJAX action on submit? Also, how can I avoid overwriting the wrong wrapper with an AjaxCommand?

edit: validateForm method:

/**
   * {@inheritdoc}
   */
  public function validateForm(array &amp;$form, FormStateInterface $form_state) {
    $email_value = $form_state-&gt;getValue('email_address');
if (empty($email_value) || !\Drupal::service('email.validator')-&gt;isValid($email_value)) {
  $form_state-&gt;setError($form['email_address'], $this-&gt;t('Please enter a valid email address.'));
}

if (mailchimp_is_subscribed('XXXXXXX', $email_value, TRUE)) {
  $form_state-&gt;setError($form['email_address'], $this-&gt;t('You are already subscribed to our newsletter.'));
}
  }
Define a class property for a sub id and append it to the form id:

class MyForm extends FormBase {

  public $sub_id = '0';

  public function getFormId() {
    return 'my_form_' . $this-&gt;sub_id;
  }

  ...
}


You can append this sub id to the wrapper as well, if you want to have different wrappers for each form:

  public function buildForm(array $form, FormStateInterface $form_state) {
    $wrapper = 'ajax-wrapper-' . $this-&gt;sub_id;
    // use $wrapper for #ajax and div container in buildForm()
    ...
  }


Then set a different sub id for each instance of the form.

For example in a block the first instance:

$form = \Drupal::classResolver()-&gt;getInstanceFromDefinition('Drupal\mymodule\Form\MyForm');
$form-&gt;sub_id = '1';
$build['form'] = \Drupal::formBuilder()-&gt;getForm($form);


and the second in preprocess:

$form = \Drupal::classResolver()-&gt;getInstanceFromDefinition('Drupal\mymodule\Form\MyForm');
$form-&gt;sub_id = '2';
$variables['form'] = \Drupal::formBuilder()-&gt;getForm($form);