Insert, replace or delete rows from a view display results programmatically

Insert, replace or delete rows from a view display results programmatically

In some cases, you may want to dynamically insert a new row into your view results, or replace an existing one with the different entity.

One of Drupal 8 solutions for this case would be an implementing the hook_views_pre_render(&$view) in your custom module. 

According to api.drupal.org documentation, this hook is called right before the render process. At this point the query has been executed, and the preRender() phase has already happened for handlers, so all data should be available. This hook can be used by themes.

The view object parameter comes with all the rows, so it is possible to replace, update or delete any of them. Look at the object structure by using kint() command provided by the Devel module.

Structure of the current row object.
Structure of the current view row object.


The _entity, index and nid are the properties that we will use.

_entity: contains node entity object to be rendered;
index: serial number of row;
nid: provides entity node id.

Let’s try a few examples:

Insert a new row with a new entity after nth row:

function hook_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'view_id' && $view->current_display == 'display_id') {
    $k = 0;
    $temp = [];
    $entity_id = 26; // entity id to insert
    $nth_row = 1; // insert after nth row
    foreach ($view->result as $key => $value) {
      if ($k == $nth_row) {
        $entity_type = 'node';
        $entity = \Drupal::entityTypeManager()
          ->getStorage($entity_type)
          ->load($entity_id);
        $tValue = new $value();
        $tValue->_entity = $entity; // replace a row
        $tValue->index = $k; // it is important to handle index properly
        $temp[] = $tValue;
        $k++;
      }
      $value->index = $k;
      $temp[] = $value;
      $k++;
    }
    $view->result = $temp; // saving results
  }
}

As a result, the view display output will have an extra dynamically inserted row.

In order to replace or delete an existing row we can identify a target row by its nid public property.

Replace a row:

function hook_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'view_id' && $view->current_display == 'display_id') {
    $alter_entity_id = 12;
    $replacement_entity_id = 1;
    foreach ($view->result as $key => $value) {
      //  kint($value); // inspect a row value for debugging purposes
      if ($value->nid == $alter_entity_id) {
        $entity_type = 'node';
        $entity = \Drupal::entityTypeManager()
          ->getStorage($entity_type)
          ->load($replacement_entity_id);
        $value->_entity = $entity; // replace a row
      }
    }
  }
}

As a result, the view display output will have a node id 1 instead of node id 12.

Delete a row:

function hook_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'view_id' && $view->current_display == 'display_id') {
    $row_delete = 12; // entity id to delete
    foreach ($view->result as $key => $value) {
      //  kint($value); // inspect a row value for debugging purposes
      if ($value->nid == $row_delete) {
        unset ($view->result[$key]); // delete a row
      }
    }
  }
}

 

Add new comment

CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.