Score:0

Ajax form ReplaceCommand functionality breaks after first fire

cn flag

I Have a form on a page which updates a single field of a Node. The form uses ajax to update the field and returns the newly saved entity and replaces the current HTML so the new field is showing up correctly.

This works fine the first time the form is fired, but breaks after that with the following error in my console:

An AJAX HTTP error occurred

There's no further error report which would tell me more about this error.

Here is my form code:

<?php

namespace Drupal\ats_tweaks\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Onboarding form.
 */
class UpdateApplicationStatusForm extends FormBase {

  /**
   * Form ID.
   *
   * @var string
   */
  protected static $formId;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    $formId = 'update_application_status_form';
    if (self::$formId) {
      $formId = $formId . '_' . self::$formId;
    }
    return $formId;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    // Instantiates this form class.
    $instance = parent::create($container);
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $node_id = $form_state->getBuildInfo()['args'][0];

    self::$formId = $node_id;
    $application = Node::load($node_id);

    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('node', 'application');
    if (isset($field_definitions['field_application_status'])) {
      $status_options = options_allowed_values($field_definitions['field_application_status']->getFieldStorageDefinition());
    }

    $form['#attributes']['id'] = $this->getFormId();

    // Application select list.
    $form['status'] = [
      '#type' => 'select',
      '#title' => $this->t('Sollicitatiestatus'),
      '#options' => $status_options,
      '#default_value' => $application->get('field_application_status')->getValue()[0]['value'],
      '#ajax' => [
        'callback' => [$this, 'submitForm'],
        'wrapper' => 'mapping',
        'effect' => 'fade',
      ],
    ];

    $form['nid'] = [
      '#type' => 'hidden',
      '#default_value' => $node_id,
      '#value' => $node_id,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $node_id = $form_state->getValues()['nid'];

    $application = Node::load($node_id);

    $application->set('field_application_status', $form_state->getValues()['status']);
    $application->save();

    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
    $storage = \Drupal::entityTypeManager()->getStorage('node');
    $node = $storage->load($node_id);

    $build = $view_builder->view($node, 'teaser');
    $form_state->setRebuild(TRUE);

    $response = new AjaxResponse();
    $response->addCommand(new ReplaceCommand('#application-' . $node_id, $build));
    return $response;
  }

}

4uk4 avatar
cn flag
This is not a good idea naming the ajax callback FormInterface::submitForm. These are two different methods. When you specify a wrapper the ajax callback only needs to return the new content of the wrapper. Put the rest of the code in the appropriate Form API methods.
Jaypan avatar
de flag
As 4x4 mentioned, you have set up your submit response and ajax response as the same function - this is your issue.
Kimimaruu avatar
es flag
Thanks for the input, (I'm the OP. created the post without signing in...). I have changed the function name to something different and removed the wrapper as this is not needed for my response. This does not however fix my error. Hope you have some other ideas
Jaypan avatar
de flag
You need to set the rebuild in the submit handler, not the ajax callback.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.