Score:0

Display field label (not key) as views page title in contextual filter

gu flag

In continuation of these questions:

I have taxonomy terms of games and a View representing them. Each game has a select-type of field called "genre" with "key|label" format. There are 16 genres, stored like that (default language is russian):

enter image description here

Then I have configured my View's Contextual filter like this:

enter image description here

Tried with "RAW value from URL" - no changes.

enter image description here

enter image description here

And it works fine with exposed filter as well as accessing URLs like /game/2 or /games/13. But it displays page title as field KEY, as a number.

All I want to do is to output corresponding LABEL.

Theoretically I could use just values in this field, but it will provide two more problems:

  1. I can't change field's storage options without losing current data.
  2. Genres are in Russian, so there will be URL issues like this - .../?field_genre_value=%D0%90+%D1%8D%D1%82%D0%BE+%D1%82%D1%80%D0%B5%D1%82%D0%B8%D0%B9

Is there a way to solve this?

Score:0
gu flag

Finally figured it out! Posting my answer for future generations.

All we need is YOUR_TEMPLATE.theme file for this.

Below is my code with comments. It might not be perfect, so if anyone will correct some things I will appreciate that.

use \Drupal\views\ViewExecutable;

// Changing views title. It does not change HEAD <title> tag!
function YOUR_THEME_NAME_views_pre_render(ViewExecutable $view) 
{
  // checkRoute() and checkArg() are custom functions and described below
  if(checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg())
  {
    // This changes view title, as well as setting $variables['page']['#title'] to the same value.
    // gamesGenreTitle() is custom function and described below.
    $view->setTitle(gamesGenreTitle($view->args[0]));
  }
}

// Here we can change HEAD <title>
function YOUR_THEME_NAME_preprocess_html(&$variables)
{
  // checkRoute() and checkArg() are custom functions and described below
  if (checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg() && isset($variables['head_title'])) 
  {

    // Unnecessary piece, tokens are needed for my purpose
    $token = Drupal::token();

    // $variables['page']['#title'] was changed in views_pre_render(), so we can change HEAD <title>.
    // I use [current-page:page-number] token to uniqueize the title
    // To improve this, we can add logic to inlcude current page number only if there is more than 1 page
    $variables['head_title'] = $variables['page']['#title'] . " | Page " . $token->replace('[current-page:page-number]');
  }
}

// In case you're using current page title in breadcrumbs, might want to change it too.
function YOUR_THEME_NAME_preprocess_breadcrumb(&$variables)
{
  // checkRoute() and checkArg() are custom functions and described below
  if(checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg() && isset($variables['breadcrumb']['2']['text']))
  {
    // You might want to var_dump($variables) before doing this trick in order to find your piece of breadcrumb.
    $variables['breadcrumb']['2']['text'] = gamesGenreTitle(getArg_0());
  }
}

// Getting allowed values of field (labels) used to make title
function gamesGenreTitle($val)
{
  $options = options_allowed_values(\Drupal::service('entity_field.manager')->getFieldStorageDefinitions('taxonomy_term')['field_NAME']);

  // Check if we are passing correct data
  if(is_numeric($val) && $val <= count($options))
  {
    return $options[$val];
  }
}

// Check if needed argument is set and numeric.
function checkArg()
{
  $arg = Drupal::routeMatch()->getParameter('arg_0');
  // In my case argument from views was passed to arg_0
  // It may vary, so try to var_dump($arg) or ksm($arg) to check if it is what you need

  return isset($arg) && is_numeric($arg);
}

// Checking current route, we need exact view and display, otherwise title will be changed on every page.
function checkRoute($check)
{
  $route = \Drupal::routeMatch()->getRouteName();
  return $route == $check;
}

// Getting arguments, passed to views.
function getArg_0()
{
  // And again, arg_0 might not be your argument, double check it with var_dump() or ksm()
  return Drupal::routeMatch()->getParameter('arg_0');
}

And another method, if you don't have a lot of field labels, you can use this in views title override field (twig is supported there):

{% if arguments.field_NAME_value == 1 %} YOUR TITLE 1 {% elseif arguments.field_NAME_value == 2 %} YOUR TITLE 2 {% endif %}

Hope this will help someone!

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.