7

Given:

  • I am using Drupal 8.
  • I have a custom "add form" of the custom entity type.
  • Form has an ajax submission.

Problem:

  • When I submit form all the values remain in fields.

Expected:

  • Form fields should be cleared after submission.

Form source code:

<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;

/**
 * Form controller for the add/edit entity forms.
 */
class MymoduleForm extends ContentEntityForm {

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);

    $form['#prefix'] = "<div id=\"{$this->getFormId()}-wrapper\">";
    $form['#suffix'] = '</div>';

    $form['actions']['submit']['#ajax'] = [
      'wrapper' => $this->getFormId() . '-wrapper',
      'callback' => array($this, 'ajaxRebuildCallback'),
      'effect' => 'fade',
    ];

    return $form;
  }

  /**
   * Callback for ajax form submission.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The rebuilt form.
   */
  public function ajaxRebuildCallback(array $form, FormStateInterface $form_state) {
    drupal_set_message(t('Entity was successfully created'));

    // @todo Clear form values.
    //$form_state->setRebuild(TRUE);
    //$form_state->setValues([]);
    /*$entity = \Drupal::entityTypeManager()->getStorage('liveblog_post')->create([]);
    $form_object = \Drupal::entityTypeManager()
      ->getFormObject('liveblog_post', 'add')
      ->setEntity($entity);*/
    //$new_form_state = new FormState();
    //$form = \Drupal::formBuilder()->rebuildForm($this->getFormId(), $form_state);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $entity = $this->getEntity();
    $entity->save();
  }

}

P.S. you can find my attempts in the ajaxRebuildCallback() method.

  • I have the very same problem ! Still searching a solution. – Gaius Nov 11 '16 at 21:39
8

You are looking for https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21FormStateInterface.php/function/FormStateInterface%3A%3AsetUserInput/8.2.x.

The values are the validated input, for setting the default values, the form system respects the original user input, which you can change with the method above.

However, for entity forms, it is a bit more complicated. $this->entity is a reference to the entity, you will still have that and it will fallback to that. What you probably need to do is create a new entity in save, assign it to $this->entity, then empty user input and $form_state->setRebuild(). That should then rebuild the form with a new and empty entity.

  • 1
    thank you for the answer. I tried the $form_state->setUserInput() as well. But I get an error with a strange message: An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (32 MB) that this server supports.. P.S. I am executing it in the MymoduleForm::save() method. Unsettling the entity and $form_state->setRebuild(); did not help. Also tried at the ::ajaxRebuildCallback(). – milkovsky Nov 14 '16 at 11:10
6

@Berdir's answer helped me to figure out the solution. We should indeed clear the user input, but we can not simply just say $form_state->setUserInput([]), because there are some system values, that should stay(e.g. form_id, form_token, _triggering_element_name, etc.).

I have created a custom method for it:

  /**
   * Clears form input.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  protected function clearFormInput(array $form, FormStateInterface $form_state) {
    // Replace the form entity with an empty instance.
    $this->entity = $this->entityTypeManager->getStorage('my_entity_type')->create([]);
    // Clear user input.
    $input = $form_state->getUserInput();
    // We should not clear the system items from the user input.
    $clean_keys = $form_state->getCleanValueKeys();
    $clean_keys[] = 'ajax_page_state';
    foreach ($input as $key => $item) {
      if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
        unset($input[$key]);
      }
    }
    $form_state->setUserInput($input);
    // Rebuild the form state values.
    $form_state->setRebuild();
    $form_state->setStorage([]);
  }

I am calling $this->clearFormInput($form, $form_state); in the MymoduleForm::save() method(the very last step of the submission).

Your Answer

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

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