When I work in Drupal, I do things programmatically as much as possible. This keeps features out of the database, which makes version control, maintainability, portability, and deployment so much easier. There are exceptions though; I find it’s worthwhile to use the GUI for adding fields to node content types. When it comes to field content display however, I always do it in code.

A challenge I came upon recently was needing to get the human-readable value of a text list field. This is the kind of field that’s set in the CMS using a dropdown or radio select, with a preset list of options.

The field settings have an “Allowed values list”, which is a set of key|label pairs. The key is the unchanging machine name, and the label is the human-readable, frontend facing value, which can be changed whenever necessary.

The “Allowed values list” might look like this:

cow|Moo Cow
dog|Doggie
pig|Piggie

Now, the goal is to be able to easily access the human-readable value programatically, so that we can display the label part whenever we need it, without having to monkey around configuring the field’s display settings.

Create and enable a custom module named mymodule. I won’t go into the details of how to set up a base custom module, if you need help with this, there are plenty of resources out there.

In your custom module, create:

modules/mymodule/src/Plugin/Field/FieldType/MyListStringItem.php

Place the follwing code in it:

<?php
namespace Drupal\mymodule\Plugin\Field\FieldType;
use Drupal\options\Plugin\Field\FieldType\ListStringItem;

// extend the base class
class MyListStringItem extends ListStringItem {
  public function getHumanValue() { // add our custom method
    $allowed_values = $this->getSetting('allowed_values');
    $value = $allowed_values[$this->value];
    return $value;
  }
}

In modules/mymodule/mymodule.module use the hook hook_field_info_alter to tell Drupal to use our class MyListStringItem for list_sting fields:

/* Implements hook_field_info_alter */
function mymodule_field_info_alter(&$info) {
  // this makes `list_sting` fields use our custom class,
  // which extends the base Drupal class for the field.
  if (isset($info['list_string']))
    $info['list_string']['class'] =
      'Drupal\mymodule\Plugin\Field\FieldType\MyListStringItem';
}

Flush the cache.

Now you can easily get the human readable value whenever you need it, like this:

$value = $node->field_my_list_string[0]->getHumanValue();

Or in a twig template:

The value is {{ node.field_my_list_string.0.getHumanValue }}

Nice!

There’s a catch though, this will only do the trick on a single-language site. In the next post, I’ll talk about how to get the translated human readable value.