1

I need a views block with a contextual date filter, based upon a date field of the currently viewed node.

What I've got so far:

  1. I already have created my base view with base filters and sorting.
  2. I've added a relation to the current node ("Get the actual content from a content revision")
  3. I've added a contextual filter Content ID, using Content ID from URL as default value

But I don't want the current node in my views block, I need the next two nodes in my views block, and I don't know how to do this part of the contextual filter:

views_node.field_date > contextual_node.field_date

Concrete use case:

I'm displaying the full view of "event node A", and on that full view of node A, I want to embed a views block, showing the next two "event nodes B and C" after the date of event node A (for selecting and ordering nodes B and C I want something similar to this pseudo-query: select * from view_nodes where view_nodes.field_mydate > context_node.field_mydate order by view_nodes.field_mydate limit 2)

3 Answers 3

2

Use hook_views_query_alter to alter query filter based on current node id or created date of node and put limit 2.

Where clause will be Like:

  1. nid > current_nid
  2. created date > current node created date (this may create issue if we have imported node in bulk)

Also we can do it from contextual filter as well just add contextual filter for current node id, greater than current node id.

1
  • If you need node field in filter then you just add that field in contextual filter and alter condition in hook_views_query_alter,
    – Prem Patel
    Dec 6, 2017 at 5:40
0

For my use case, I want to filter pages than are older than current page.

Contextual filter cannot work as we don't have access to the operator : @see Is there a specific reason that views contextual filters lack the ability to specify the operator?

So I have for my work around:

1x contextual filter:

  • Use content Id from URL + content validator content (exclude from results)

1x normal views filter:

  • filter by created date is less than current with dummy value "2020-10-20 00:00:00"

On the block layout -> block settings I use "Content: ID Node from ID".

Then in the theme layer to override "2020-10-20 00:00:00" with node created date:


use Drupal\Core\Plugin\ContextAwarePluginInterface;

/**
 * Implements hook_preprocess_block__views_block__VIEW_ID__DISPLAY_ID().
 */
function mytheme_preprocess_block__views_block__alumni_hub_previous_lessons_block_1(&$variables, $hook) {
  if (!isset($variables['elements']['#plugin_id'])
    || !isset($variables['elements']['#configuration'])) {
    return;
  }
  $block_manager = \Drupal::service('plugin.manager.block');
  // Plugin ID format is: views_block:VIEW_ID-DISPLAY_ID.
  $plugin_block = $block_manager->createInstance($variables['elements']['#plugin_id'], $variables['elements']['#configuration']);
  // Inject runtime contexts.
  if ($plugin_block instanceof ContextAwarePluginInterface) {
    $contexts = \Drupal::service('context.repository')->getRuntimeContexts($plugin_block->getContextMapping());
    \Drupal::service('context.handler')->applyContextMapping($plugin_block, $contexts);
    // Get the node entity from the contextual value now.
    $contextual_values = $plugin_block->getContextValues();
    if (isset($contextual_values['nid'])
      && $contextual_values['nid']->hasField('created')
      && !$contextual_values['nid']->get('created')->isEmpty()) {

      $date_timestamp = $contextual_values['nid']->created->value;
      $plugin_view = $plugin_block->getViewExecutable();
      $filter = $plugin_view->display_handler->getHandler('filter', 'created');
      // Actually line that changes stuff.
      // Set filter to show nodes earlier than current ndoe.
      $filter->value['value'] = \Drupal::service('date.formatter')->format($date_timestamp, 'custom', 'Y-m-d H:i:s');
      // Good to change options too.
      $filter->options['value'] = $filter->value;
      // Override render array.
      $variables['content'] = $plugin_block->build();
    }
  }
}

0

Would this not work with tokens? It provides the created-date for the current page/node. Then create a view showing nodes sorted by date. Add a filter where date is >= the node date or <= the node date. For the pager, chose show 1 and offset 1, so that only the "prev" or "next" item displays.

To filter starting from a certain date you'd use the token value. https://www.drupal.org/project/token

Another approach is setting filter values programmatically.There are some examples here: How to get contextual filter in hook_views_query_alter or hook_views_pre_execute?

Pseudo code:

$node = \Drupal::routeMatch()->getParameter('node');
$view = Views::getView('test_view');

if (is_object($view) && is_object($node)) {
  $view->setArguments($args);
  $view->setDisplay('block');

  // Filter is applied by reference (no need for setHandler()).
  $filter = $view->display_handler->getHandler('filter', 'created');
  $filter->value['value'] = \Drupal::service('date.formatter')->format($node->created->value, 'custom', 'Y-m-d H:i:s');
  // Good to change options too.
  $filter->options['value'] = $filter->value;

  $view->preExecute();
  $view->execute();

  print $view->render();
}
4
  • That doesn't seem to be my use case. I'm displaying the full view of node A, and on that full view of node A, I want to embed a views block, showing the next two nodes B and C (for selecting and ordering nodes B and C I want something like where nodes_b_and_c.field_mydate > node_a.field_mydate)
    – Hudri
    Dec 5, 2017 at 9:23
  • I think I didn't describe my problem well enough (sorry, english isn't my mother tongue): I do know how to embed a view block in a node template. And I know that I can contextually filter with taxonomy terms, but the same option doesn't exist for "normal" non-taxonomy-reference fields. I don't know how to pull in the date field from the context node into the contextual filter.
    – Hudri
    Dec 5, 2017 at 16:05
  • I understand. I'd recommend trying the token module (or advanced token module - google search). It allows using typing variables into fields used in the view. For example, node:created.
    – s6712
    Dec 5, 2017 at 19:14
  • Will update comment above. If tokens didn't work, you'd follow solution #2: Create a View and embed using block. Then set filters with your embed code or mytheme_views_alter in mytheme.theme php.
    – s6712
    Dec 5, 2017 at 20:55

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.