Drupal - How do I send a variable value from my form to another page using the POST method?

This is how I send information from one form to another.

In the first page:

use \Drupal\Core\Url;

function submitForm(array &$form, FormStateInterface $form_state){
  drupal_set_message($this->t('@candidate_name! Wow! Nice choice! Thanks for telling us!', array('@candidate_name' => $form_state->getValue('candidate_name'))));

  $params['query'] = [
    'candidate_name' => $form_state->getValue('candidate_name'),
  ];

  $form_state->setRedirectUrl(Url::fromUri('internal:' . 'second_page', $params));
}

In the second page:

public function buildForm(array $form, FormStateInterface $form_state) {   
  $candidate_name = \Drupal::request()->query->get('candidate_name');

  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Candidate Name:'),
    '#required' => TRUE,
    '#value' => $candidate_name,
  );

  return $form;
}

EDIT: For POST method I never see it before, but you can create in the first page a session var and use this var in the second var after the redirection. Take a look in Storing Session Data with Drupal 8.

SECOND EDIT: It seems that the correct way todo this is with PrivateTempStore, if you go to see the CommentAdminOverview in Core you will see this:

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
      ...
      $info = [];
      /** @var \Drupal\comment\CommentInterface $comment */
      foreach ($comments as $comment) {
        $langcode = $comment->language()->getId();
        $info[$comment->id()][$langcode] = $langcode;
      }
      $this->tempStoreFactory
        ->get('comment_multiple_delete_confirm')
        ->set($this->currentUser()->id(), $info);
      $form_state->setRedirect('comment.multiple_delete_confirm');
    }
  }

In this page you collect the comment id that you want to delete and made a redirect, and the comment deletion happens in comment.multiple_delete_confirm (ConfirmDeleteMultiple) that have the following code:

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $this->commentInfo = $this->tempStoreFactory->get('comment_multiple_delete_confirm')->get($this->currentUser()->id());
    if (empty($this->commentInfo)) {
      return $this->redirect('comment.admin');
    }
    /** @var \Drupal\comment\CommentInterface[] $comments */
    $comments = $this->commentStorage->loadMultiple(array_keys($this->commentInfo));
  ...
  }

So, we don't have a POST method from one form to another in Drupal 8 but this can be solved in this way.


One way you can do this is to add a query string with the value on it with setRedirect.

$form_state->setRedirect('second_page', ['name' => $form_state->getValue('name')]);

Then, read it in the next form:

// top of file
use Drupal\Core\Component\Utility\Xss;

$name = Xss::filter(\Drupal::request()->get('name'));

$form['name'] = array(
  '#type' => 'textfield',
  '#title' => t('Candidate Name:'),
  '#default_value' => isset($name) ? $name : '',
  '#required' => TRUE,
);

Note, I wouldn't do this for more sensitive information like credit card numbers or anything like that.


Quite a pickle! Here are some suggestions:

Solution 1: Session to the rescue!

  • After the first form is submitted, validated and processed, store the relevant values (the ones you want to pass to the second form) in the session.
  • While building the second form, use the values stored in session as default values to pre-populate it.

Solution 2: Multi-step form

  • Merge the 2 forms into one giant form. Put the elements of the first form in one container and the elements of the second form in another container. Set #access to FALSE for the second container to hide the second container.
  • After the user submits the info in the first part of the form, hide the first container and show the second one!

Reference: See the form examples provided in the examples module.

Solution 3: Form states?

Depending on situation, you can also consider using form states. If you use form states, the hiding and showing can be done in the client-side. So the form will make one request to the server once it has all the data.

Solution 4: Change form action!

Depending on situation, you may even consider changing the action attribute of the form so that the values are submitted to the URL you specify in the form's action attribute.

Tags:

Forms

8