I have a View which returns 5 entities of the same type. AJAX - enabled, filters and exposed filters, all working fine.

I need to add a new result, a user - defined entity, at the top of the View results. This programmatically added row should not be affected when the exposed filters are used and should remain at the top of the View, on top of the other 5 returned results, no matter what.

I managed to add this with hook_views_post_execute() but when I use the exposed filters the View returns to its original results and my addition is lost, because AJAX is enabled on this View. hook_views_post_execute() doesn't seem to have any effect after the initial page load.

What is a good alternative for this scenario ie alter the View in a way that's not affected by the AJAX refresh?

  • In the UI you can embed a different view into the header area of your view. Wouldn't that work? – enzipher Mar 25 '20 at 22:45
  • Attachments and headers also disappear on AJAX refresh. – webmaniac Mar 25 '20 at 22:51
  • Make views exposed form as block, make user result views as block. Place these blocks above of View with 5 entities. That's all... – Nikit Mar 25 '20 at 23:25
  • @nikit the View structure needs to stay as is, not break it down into blocks as this will also create a huge need for theming changes. The required solution is to inject the one “independent of filters” entity between the filters and the dynamic results and make it unaffected by any change coming from the exposed filters. – webmaniac Mar 26 '20 at 8:14
  • @webmaniac I don't think that's big problem for theming changes - exposed block and view will have one common classes. Also you can assign class in view settings. The same for users view. – Nikit Mar 26 '20 at 11:46

When checking the current route match in a Views Ajax request you get the route of the Views Ajax endpoint views/ajax and not the route of the page where the View is placed on.

However, Ajax requests contain the original path of the View and ViewAjaxController::ajaxView() puts this path in the global current path stack (for the pager to work correctly).

So if the path is no longer in the request

$path = \Drupal::request()->request->get('view_path');

it should be transfered to:

$path = \Drupal::service('path.current')->getPath();

Which should then point to the node route you are looking for.

  • Unfortunatelly this returns /views/ajax. I think I'm getting somewhere with \Drupal::request()->server->get('HTTP_REFERER') and \Drupal::request()->getSchemeAndHttpHost(). – webmaniac Mar 26 '20 at 20:38
  • You can't rely on the refererer, not all clients provide one. If view_path is not transferred already to the current path it should still be present in the request. – 4k4 Mar 26 '20 at 20:44
  • 4k4 can you elaborate please, I don't seem to get anythign in view_path. – webmaniac Mar 26 '20 at 20:56
  • See the edited answer. – 4k4 Mar 26 '20 at 21:20
  • \Drupal::service('path.current')->getPath(); still returns /views/ajax. – webmaniac Mar 26 '20 at 21:26

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.