web-dev-qa-db-ja.com

AJAX submitの後にフォームフィールドをクリアします

与えられた:

  • Drupal 8.を使用しています。
  • カスタムエンティティタイプのカスタム「追加フォーム」があります。
  • フォームにはajax送信があります。

問題:

  • フォームを送信すると、すべての値がフィールドに残ります。

期待される:

  • フォームフィールドは送信後にクリアする必要があります。

フォームのソースコード:

_<?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();
  }

}
_

追伸私の試みはajaxRebuildCallback()メソッドで見つけることができます。

7
milkovsky

@Berdirの答えは私が解決策を理解するのに役立ちました。実際にユーザー入力をクリアする必要がありますが、単に$form_state->setUserInput([])と言うことはできません。これは、システム値が残っているためです(例:_form_id_、_form_token_、__triggering_element_name_など)。

私は カスタムメソッド を作成しました:

_  /**
   * 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([]);
  }
_

$this->clearFormInput($form, $form_state);メソッドでMymoduleForm::save()を呼び出しています(送信の最後のステップ)。

8
milkovsky

あなたが探している https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21FormStateInterface.php/function/FormStateInterface%3A%3AsetUserInput/8.2.x

値は検証された入力であり、デフォルト値を設定するために、フォームシステムは元のユーザー入力を尊重します。これは、上記の方法で変更できます。

ただし、エンティティフォームの場合は少し複雑です。 $ this-> entityはエンティティへの参照です。これは引き続き存在し、フォールバックします。おそらくあなたがする必要があるのは、saveで新しいエンティティを作成し、それを$ this-> entityに割り当て、次にユーザー入力を空にして$ form_state-> setRebuild()を実行することです。その後、新しい空のエンティティでフォームを再構築します。

8
Berdir