Multiple forms on page

I am trying to get multiple forms to work in a views display. All of the forms uses AJAX, but they appear to be interfering with each other.

One form is the Views Bulk Operations form that turns the views table into a ‘viewsForm’. The second form is a ‘quick edit’ form available on each row in the view. The problem is when I submit any of the forms from the quick edit, it tries to also submit the ‘viewsForm’ form (which it shouldn’t be doing), resulting in validation errors on that form. It’s also not picking up my ajax callback for my custom form, as witnessed by the ‘ajax callback is empty or not callable’ in the dblog.

If I disable views bulk operations, this works as intended, but with multiple forms on the page, I can’t figure out how to tell the ‘submit’ button I am using to only submit the form belonging to the submit button.

I have provided my formbuilder class for reference

<?php  namespace Drupalrequest_systemForm;  use DrupalCoreFormFormBase; use DrupalCoreFormFormStateInterface; use DrupalCoreAjaxAjaxResponse; use DrupalCoreAjaxReplaceCommand; use DrupalCoreAjaxHightlightCommand;  /**  * Provides a Request System form.  */ class QuickEditForm extends FormBase {    public $sub_id = 0;   public $entity_id = 0;    /**    * {@inheritdoc}    */   public function getFormId() {     return 'request_system_quick_edit-' . $this->sub_id;   }    /**    * {@inheritdoc}    */   public function buildForm(array $form, FormStateInterface $form_state) {      $entity = Drupal::entityTypeManager()->getStorage('lms_request')->load($this->entity_id);          $options = [];      $options['_none'] = '- Select One -';      if ($entity->bundle() == 'book_request') {       $statuses = Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties([         'vid' => 'book_request_status',       ]);     }      // Only show 'available from vendor' and 'Pending'     foreach ($statuses as $status) {       if ($status->getName() == 'Pending' || $status->getName() == 'Available From Vendor') {         $options[$status->id()] = $status->getName();       }              if ($status->id() == $entity->field_request_status->getString()) {         $options[$status->id()] = $status->getName();       }     }      $form['quick_edit'] = [       '#type' => 'container',       '#id' => 'quick-edit-wrapper-'. $this->sub_id,     ];      $form['quick_edit']['status'] = [       '#type' => 'fieldset',       '#title' => 'Status Updates',       '#name' => 'update-wrapper',     ];      if (!$entity->field_aph_shipment_number->isEmpty() || !$entity->field_library_shipment_number->isEmpty()) {       $form['quick_edit']['status']['value'] = [         '#type' => 'item',         '#title' => 'Request Status: ',         '#markup' => Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($entity->field_request_status->getString())->getName(),       ];        // Display message indicating item is part of a shipment       $form['quick_edit']['status']['shipment_number'] = [         '#markup' => 'This request is part of a shipment.',       ];     }     else {       // Disable this field if the request status is not 'Pending' or 'Available from Vendor', or if the item belongs to a shipment       $form['quick_edit']['status']['value'] = [         '#type' => 'select',         '#title' => 'Status',         '#options' => $options,         '#default_value' => $entity->field_request_status->getString(),       ];        if ($entity->field_request_status->getString() != Drupalrequest_systemControllerRequestSystemController::getStatus('Pending') && $entity->field_request_status->getString() != Drupalrequest_systemControllerRequestSystemController::getStatus('Available From Vendor')) {         $form['quick_edit']['status']['value']['#disabled'] = TRUE;       }     }      $form['quick_edit']['status']['message'] = [       '#type' => 'textarea',       '#title' => $this->t('Message'),     ];      $form['quick_edit']['status']['notify_user'] = [       '#type' => 'checkbox',       '#title' => 'Notify Borrower',     ];      // Allow editing of the APH catalog #      $form['quick_edit']['other'] = [       '#type' => 'fieldset',       '#title' => 'Other',       '#name' => 'other-wrapper',     ];      $form['quick_edit']['other']['aph_catalog_number'] = [       '#type' => 'textfield',       '#title' => 'APH Catalog #',       '#default_value' => $entity->field_attached_copy_aph_number->getString(),       '#description' => $entity->field_attached_copy_main_record->isEmpty() ? '' : 'Unable to change APH catalog number when a main record is assigned.',       '#disabled' => $entity->field_attached_copy_main_record->isEmpty() ? FALSE : TRUE,     ];      $form['quick_edit']['id'] = [       '#type' => 'hidden',       '#value' => $this->entity_id,     ];      $form['quick_edit']['actions'] = [       '#type' => 'actions',     ];     $form['quick_edit']['actions']['submit'] = [       '#type' => 'submit',       '#value' => $this->t('Save'),       '#ajax' => [         'callback' => '::quickEditAjax',         'wrapper' => 'quick-edit-wrapper-'. $this->sub_id,       ],       '#validate' => '::validate',       '#limit_validation_errors' => [['id'],['status']],       '#submit' => ['::quickEditAjaxSubmit'],     ];      // $form['quick_edit']['actions']['cancel'] = [     //   '#type' => 'submit',     //   '#value' => 'Cancel',     // ];      return $form;   }    /**    * {@inheritdoc}    */   public function validateForm(array &$form, FormStateInterface $form_state) {     $values = $form_state->getValues();      $entity = Drupal::entityTypeManager()->getStorage('lms_request')->load($values['id']);      if ($values['status'] == Drupalrequest_systemControllerRequestSystemController::getStatus("Shipped From Loan Library")) {       if (count($entity->field_imcid->referencedEntities()) == 0) {         $form_state->setErrorByName('status','Cannot mark this item shipped since no library item is attached.');       }     }   }    /**    * {@inheritdoc}    */   public function submitForm(array &$form, FormStateInterface $form_state) {    }    public function quickEditAjax(&$form, FormStateInterface $form_state) {     $values = $form_state->getValues();      if ($form_state->hasAnyErrors()) {       $form['status_messages'] = [         '#type' => 'status_messages',         '#weight' => -1000,       ];       $form['#sorted'] = FALSE;     }          $response = new AjaxResponse();      $status = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($values['status']);     $response->addCommand(new ReplaceCommand('.request-status-'. $values['id'],$status->getName()));     $response->addCommand(new ReplaceCommand('#quick-edit-wrapper-'. $this->sub_id,$form));     $response->addCommand(new HightlightCommand('#row-'. $values['id']));      return $response;   }    public function quickEditAjaxSubmit(&$form, FormStateInterface $form_state) {     $values = $form_state->getValues();      // First load the entity     $entity = Drupal::entityTypeManager()->getStorage('lms_request')->load($values['id']);      $entity->set('field_request_status',$values['status']);     $entity->save();      $form_state->setRebuild();   }  } 

And the way I am rendering the form is via

$form = Drupal::classResolver()->getInstanceFromDefinition('Drupalrequest_systemFormQuickEditForm'); $form->sub_id = $entity->id(); $form->entity_id = $entity->id(); $build['form'] = Drupal::formBuilder()->getForm($form); 

It appears that when the view is rendered, it’s combining all of the forms into a single , so when you click ‘Save’ on the sub-form, it’s actually submitting the views bulk operations form. I am not sure how to resolve this or to get it to stop doing this.

I have been banging my head on this for two weeks trying to get this resolved, and can’t figure out what the problem is.

Any help would be GREATLY appreciated.

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Multiple forms on page

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.