Tabs for views contextual arguments

Views have exposed filters to allow users to filter the results. But if you have a contextual argument, you have to provide a link for users to click on. Here's a way to do that with local tasks for each of the available contextual arguments.

We're going to build a simple schedule, with tabs for days of the week. Let's say you are building a site for an upcoming 1 week Drupal course you're teaching.

  1. Start by creating the Days taxonomy and filling it with the ones you need.
  2. Set up a Sessions content type that references the Days taxonomy.
    1. Create some content for each day.
  3. Create a view that lists sessions.
    1. Relate to the Days taxonomy term.
    2. Create a contextual argument on Days name.
    3. Set path to /schedule

With the view set up, you can put a day into the contextual filter and should see the right content. The term name contextual argument is not case sensitive and accepts spaces, so if your days are "Day 1" instead of days of the week, the view should work for "/schedule/day 1" as well as "/schedule/Friday". If you want better options for tuning this, check out the Views taxonomy term name into ID module.

In order to create the local tasks, we need to use a Deriver (see DeriverBase). This is used to define a plugin that sets up multiple instances. In other words, we're defining a local task that returns multiple tabs.

In your module, add a MODULE.link.tasks.yml file:

views_argument_tabs.schedule.day:
  base_route: view.schedule.page_1
  route_name: view.schedule.page_1
  deriver: 'Drupal\views_argument_tabs\Plugin\Derivative\ViewsArgumentTabs'
  weight: 100

Views routes are view.VIEW_NAME.DISPLAY_NAME.

This definition says we're adding tabs to the Schedule view page, and to use our custom deriver.

<?php

namespace Drupal\views_argument_tabs\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Component\Utility\Html;

/**
 * Tabs for views arguments.
 */
class ViewsArgumentTabs extends DeriverBase {

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    // Load Days taxonomy terms.
    $days = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('days');
    foreach ($days as $day) {
      // Create tab identifier.
      $day_id = strtolower(Html::cleanCssIdentifier($day->name));
      // Get base_route and route_name from links.task.yml definition.
      $this->derivatives[$day_id] = $base_plugin_definition;
      // Set tab title to Day's name.
      $this->derivatives[$day_id]['title'] = $day->name;
      // Route parameter is what you defined in the view path.
      $this->derivatives[$day_id]['route_parameters']['arg_0'] = strtolower($day->name);
    }
    return parent::getDerivativeDefinitions($base_plugin_definition);
  }

}

In the ViewsArgumentTabs deriver, we load the Days and create a derivative tab for each one. $day_id is a machine name for the local task. ['route_parameters']['arg_0'] is what sets the value of the contextual argument.

Final product

View with argumen tabs

Tags
Routing Views