In Drupal 7, for a view where I wanted to replace every instance of 'am' with 'a.m.' (with a similar replacement for pm/p.m.) in the output, I did this:

function mymodule_views_post_render(&$view, &$output, &$cache) {
  if ($view->name == 'target_view') {
    $replace_pairs = array(
      ' am ' => ' a.m. ',
      ' pm ' => ' p.m. ',
    $output = strtr($output, $replace_pairs);

How do I achieve the same result in Drupal 8? The documentation for the D8 version of hook_views_post_render() is broken/incomplete, but it does mention strtr(), so I imagine something similar should work.

I've already figured out that my if statement will need to test against $view-storage->id() instead, and I've noticed that $output is an array (rather than a string) in D8, but I'm not seeing anything appropriate to target in that array. I am new to D8; can someone show me the way?


In your custom module, create module_name.views.inc file and add following code.

use \Drupal\views\ViewExecutable;
use \Drupal\views\Plugin\views\cache\CachePluginBase;

function custom_module_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
  if ($view->id() == 'VIEW_NAME') {
    $html = \Drupal::service('renderer')->renderRoot($output['#rows']);
    $replace_pairs = array(
      ' am ' => ' a.m. ',
      ' pm ' => ' p.m. ',
    $html =  strtr($html, $replace_pairs);

    $output['#rows'] = $html;

Replace VIEW_NAME with your view name and clear drupal cache.

  • Nice trick, normally you should use renderRoot() only for responses in a controller. If you use it in other places like here you have to extract the cache data and add it to $output. Otherwise nodes or what is listed in the view won't get refreshed when modified in the database (this depends on the configuration of the view, not all views will be affected).
    – 4k4
    Dec 5 '17 at 11:09
  • Note that this hook can be invoked from within a custom theme (instead of a module) if that makes more sense for the modifications that are being made and that there is no requirement for it to be placed in module_name.views.inc, though that may be the best practice.
    – komlenic
    Jan 9 '19 at 14:27

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.