4

I want to build kind of a search form in Drupal 8: On submit, it shall load itself again, but below the results shall rendered. And the URL shall contain the search term, so that the result page is linkable.

This is my minimal example. My current problem ist, that the submitted form value is not fed to $form_state.

public function buildForm(array $form, FormStateInterface $form_state) {

  $form_state->setMethod('get');

  $query = $form_state->getValue('query');
  // Unfortunately, this is empty, even after submit.

  $form['query'] = array(
    '#type' => 'textfield',
    '#title' => $this->t('Query'),
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Search'),
  );

  return $form;
}

public function submitForm(array &$form, FormStateInterface $form_state) {
  $form_state->setRebuild();
  $form_state->setAlwaysProcess(TRUE);
}

When I comment out $form_state->setMethod('get');, it is working as I want: query is readable in the rebuild form and set as default value in the text field.

But with setMethod('get');, query is empty and no default is set.

I thought that $form_state->setAlwaysProcess(TRUE); makes sure the values get processed, even via GET method, as the documentation suggests. But apparently, something is missing. Any ideas, what?

  • I'd advise ditching setMethod and instead do an AJAX implementation, and have the commands insert results into an HTML wrapper ready to receive them. – Kevin Jan 24 '17 at 18:48
  • Well, sure, I could somehow manually fill in the GET-submitted values into the form. But unlike the minimal example, my actual form is way more complicated and may also change in the future. So I wanted to avoid future work of constantly adapting the GET->form filling and rely solely on the Form API. – But I really wonder: Is there really no way to tell Drupal to treat the GET params like POST params? – Georg Jähnig Jan 25 '17 at 15:14
  • AJAX is part of the Form API. In the past, I have changed submit buttons to #ajax with properties and callbacks, in them, you can set AJAX commands. But yeah if your actual form is more complex than shown, maybe not. Perhaps $foo = \Drupal::request()->get('url_param')? – Kevin Jan 25 '17 at 15:17
5

I could solve the problem myself, based on this solution for Drupal 7.

Instead calling the form directly in the router, I define a page callback in my_module.routing.yml.

my_module.form:
  path: '/my-module-form'
  defaults:
    _title: 'My module form'
    _controller: '\Drupal\my_module\Controller\MyModuleController::searchForm'

In MyModuleController, I load my form via the builder.

public function searchForm() {

  $form_state = new FormState();
  $form_state->setMethod('get');
  $form_state->setAlwaysProcess(TRUE);
  $form_state->setRebuild();

  $form = \Drupal::formBuilder()->buildForm('Drupal\my_module\Form\MyModuleSearchForm', $form_state);
  unset($form['form_build_id']);
  unset($form['form_id']);

  return $form;
}

The code of form then is like in the question above.

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.