I have two forms in Drupal 8 that I am prepopulating values with if a value exists in the query string.

$keywords = Xss::filter($this->requestStack->getCurrentRequest()->get('keywords'));

$form['keywords'] = [
      '#type' => 'textfield',
      '#maxlength' => 128,
      '#size' => 64,
      '#default_value' => Unicode::strlen($keywords) ? $keywords : '',
      '#prefix' => '<div class="search-box__input js-search-input">',
      '#suffix' => '</div>',
      '#required' => TRUE,
      '#attributes' => [
        'placeholder' => Unicode::strlen($keywords) ? $keywords : t('Search Site'),

Works great for authenticated users, but for anonymous users, they are always seeing the last term entered, despite the query string having nothing in the URL. Even if I close the browser and come back, the term is still in the input field. I assume it gets cached.

The form is being attached as a twig variable to a block containing other content:

 * Implements hook_preprocess_block().
 * @param $variables
function mytheme_preprocess_block(&$variables) {
  if (isset($variables['elements']['content']['#block_content'])) {
    $variables['block_content'] = $variables['elements']['content']['#block_content'];

  // inject main nav search form to block template for main_nav only
  if ($variables['elements']['#id'] == 'main_nav') {
    $variables['main_nav_search_form'] = \Drupal::formBuilder()->getForm('\Drupal\mymodule_search_forms\Form\MainNavSearchForm');

Is there a way to change this so that does not happen? Any cache tag I could use?


1 Answer 1


What you need need to do, is not to use a cache tag but a cache context. In your specific scenario you want to use url.query_args:keywords. In code that would look like this

$form['keywords'] = [
   '#cache' => ['contexts' => ['url.query_args:keywords']],

For reference.

Cache tags are used to invalidate cache. Like if a cache element is tagged with node:1 and node with nid 1 is updated, then all cache containing node:1 cache tag is invalidated (other tags are also invalidated).

Cache contexts are used if cached element exists in multiple variations based on something like the query arg. What happens is that multiple cache entries are created and they will all be invalidated based on the same logic (cache tags).

  • 1
    Thanks, this was helpful also to shed light on the cache subsystem.
    – Kevin
    Feb 13, 2017 at 17:02
  • 4
    +1, this is a very good answer. But strange is the problem with anonymous users, because the internal page cache does vary by the full url by default. And the context wouldn't help, because it's not used here. You need it though, because the block has to vary by this context no matter if it's used by a logged in or anonymous user.
    – 4uk4
    Feb 13, 2017 at 17:14
  • Nailed it. Added both cache contexts (session and keyword) problem solved.
    – Kevin
    Feb 13, 2017 at 17:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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