1

I have a form(which is extending the FormBase class) that requires entity as argument(but I am not manipulating with this entity so that's why I am not using the EntityForm which is irrelevant to this issue but just FYI). The form uses data from the entity to build the form id. I am instantiating the form as object and I am keeping the entity as property on the form.

Due to the fact that I have multiple such forms on a single page I need the form id to be unique and matching the provided entity object to avoid collision of submitted values. In Drupal 7 this was taken care of via hook_forms().

Now I want to ajaxify this form but there is an issue that after the first submission the entity object is no longer available to the form. I have stored the data I need in the $form_state but I cannot access this in the getFormId() method.

So I have made the form id non-unique and each form instance has the same id. I have tried to get around this issue by setting the form id in the form array itself as #id attribute but that did not helped.

So my question is how to have an ajaxified form with unique form id that is based on data from provided argument to the form?


This is how I am invoking the form(in lazy loader):

$entity = $this->entityManager->getStorage($entity_type)->load($entity_id);
$form = new MyForm($entity);
return $this->formBuilder->getForm($form);

and the form itself:

class MyForm extends FormBase {

  private $entity;

  public function __construct($entity) {
    $this->entity = $entity;
  }

  public function getFormId() {
    return 'my_form_' . $this->entity->getEntityTypeId() . '_' . $this->entity->id();
  }

}
  • I'm not sure I understand the exact problem. I have two projects that are using a similar approach to build a unique form Id (poll and simplenews subscription block forms), but they aren't using ajax at the moment. The way ajax submissions work now in HEAD is that the code is just executed again until it finds the form as it is no longer cached. So I really don't understand why that shouldn't work. – Berdir Aug 20 '15 at 20:23
  • Before I have ajaxified the form it worked just fine. But when ajaxified it no longer has the $entity object available to extract the data from it for generating proper form id. In form array itself I can preserve the needed data in $form_state's storage. But the getFormId() does not have access to it so it will not rebuild properly and if there are multiple such form on a single page they all submit the same data. – user21641 Aug 20 '15 at 20:29
  • @Berdir could you recommend maybe another way of instantiating the class object...or another way to provide the argument to the form? Or even some form factory? – user21641 Aug 21 '15 at 6:16
  • If I hardcode the unique form id, everything is working. So the form array itself is not a problem. Just the form id in the getFormId() method. – user21641 Aug 21 '15 at 6:38
  • I've tried the Poll approach but removing the form constructor and setting the entity object via designated method didn't help. – user21641 Aug 21 '15 at 7:01
1

So the issue was that I was calling the getFormId() in the form itself to build the html id for the ajax wrapper. For rebuilt form the entity object that I provided as argument to constructor was not available anymore so calling this method caused it to look for that entity object to extract data to build the id from and since it no longer exists it caused this issue.

0

I had a similar issue in D7 and finally solved it by wrapping all form elements with a '#type' => 'container' element which got prefixed/suffixed with a div holding a unique drupal_html_id($id).

Then in the AJAX callback (added to a '#type' => 'select' element) I returned the whole container instead of just returning the one element I needed ajaxified. That way drupal_html_id($id) ensured the id being unique for every single AJAX action.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy