n Creating a custom Views field in Drupal 8 | CodimTh

Please Disable Your Browser Adblock Extension for our site and Refresh This Page!

our ads are user friendly, we do not serve popup ads. We serve responsible ads!

Refresh Page
Skip to main content
On . By CodimTh

In this article I am going to show you how to create a custom counter Views field in Drupal 8. 

So let's get started by creating a small module called counter_field:

create counter_field.info.yml:

name: Views Counter Field
description: 'Module drupal 8 to add counter field to views'
package: 'Custom'
core: 8.x
type: module

To create a custom views field, we need to implement hook_views_data() in counter_field.views.inc

create counter_field.views.inc:

 * @file
 * Contains counter_field\counter_field.views.inc..
 * Provide a custom views field data that isn't tied to any other module. */
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Render\Markup;
use Drupal\field\FieldConfigInterface;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\system\ActionConfigEntityInterface;
 * Implements hook_views_data().
function counter_field_views_data() {
  $data['views']['table']['group'] = t('Custom Global');
  $data['views']['table']['join'] = [
    // #global is a special flag which allows a table to appear all the time.
    '#global' => [],
  $data['views']['counter_views_field'] = [
    'title' => t('Counter views field'),
    'help' => t('My awesome custom views field plugin.'),
    'field' => [
      'id' => 'counter_views_field',
  return $data;

In this implementation we extend the views table definition by adding a new field called counter_views_field. Although there are many more options you can specify here, these will be enough for our purpose. The most important thing to remember is the id key (under field) which marks the id of the views plugin that will be used to handle this field.


In Drupal 8 we have something called plugins and many things have now been converted to plugins, including views handlers. So let's define our class inside the src/Plugin/views/field folder of our module:

create src/Plugin/views/field/CounterViewsField.php:

namespace Drupal\counter_field\Plugin\views\field;
use Drupal\Component\Utility\Random;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
 * A handler to provide a field that is completely custom by the administrator.
 * @ingroup views_field_handlers
 * @ViewsField("counter_views_field")
class CounterViewsField extends FieldPluginBase
   * {@inheritdoc}
  public function usesGroupBy()
    return FALSE;
   * {@inheritdoc}
  public function query()
    // Do nothing -- to override the parent query.
   * {@inheritdoc}
  protected function defineOptions()
    $options = parent::defineOptions();
    $options['counter_start'] = ['default' => 1];
    $options['hide_alter_empty'] = ['default' => FALSE];
    return $options;
   * {@inheritdoc}
  public function buildOptionsForm(&$form, FormStateInterface $form_state)
    $form['counter_start'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Starting value'),
      '#default_value' => $this->options['counter_start'],
      '#description' => $this->t('Specify the number the counter should start at.'),
      '#size' => 2,
    parent::buildOptionsForm($form, $form_state);
   * {@inheritdoc}
  public function render(ResultRow $values)
    // Note:  1 is subtracted from the counter start value below because the
    // counter value is incremented by 1 at the end of this function.
    $count = is_numeric($this->options['counter_start']) ? $this->options['counter_start'] - 1 : 0;
    $pager = $this->view->pager;
    // Get the base count of the pager.
    if ($pager->usePager()) {
      $count += ($pager->getItemsPerPage() * $pager->getCurrentPage() + $pager->getOffset());
    // Add the counter for the current site.
    $count += $this->view->row_index + 1;
    return $count;

In our example class, we have 3 methods:

defineOptions(): method to specify what configuration options we need for this field.

buildOptionsForm(): is responsible for creating the form for the configuration options we declared earlier.

render(): method which is the most important and which deals with output. we use it to actually render the content of the field for each result.


And this is my final output:

custom views field


Next steps

  • Clear your Drupal 8 caches. To do this I use this Drush command: drush cr if you don’t currently use Drush, I highly recommend using it, or the Drupal Console.
  • Now, go back to your site, and you should be able to see the custom views field you have just created.
  • I hope you found this article useful. let me know if you have any questions and I’ll be happy to answer them.



Riadh Rahmi

Senior Web Developer PHP/Drupal & Laravel

I am a senior web developer, I have experience in planning and developing large scale dynamic web solutions especially in Drupal & Laravel.

Web Posts


Page Facebook