I have a custom content entity that renders fine in its page view and form. I'm now trying to view one of its fields in a table using an EntityListBuilder, but the following code throws an error message:

public function buildRow(EntityInterface $entity) {
  $row['id'] = $entity->id();
  $row['email'] = $entity->email->view();

  return $row + parent::buildRow($entity);

Results in:

Fatal error: Call to undefined method Drupal\my_module\Entity\MyEntity::render() in /.../core/lib/Drupal/Core/Template/Attribute.php on line 294

Apparently the view builder expects a render() method, which I do not have, and which I do not want to implement, since the entity renders fine otherwise...

Also tried EntityViewBuilder::viewField() with no success.

Even when I'm viewing a node instead of my custom entity, I get the same message.

  • As an aside, I don't know why I'm bothering with ListBuilder. I've switched to views now and it's much less of a pain. – Hendrik Nov 6 '15 at 6:42

The function buildRow returns a render array. You can put simple strings directly in the array, because later it will be put in another html structure like a table. An example from core, where it is used both ways (CommentTypeListBuilder.php):

public function buildRow(EntityInterface $entity) {
    $row['type'] = $entity->label();
    $row['description']['data'] = ['#markup' => $entity->getDescription()];
    return $row + parent::buildRow($entity);

So using the '#markup' element is optional. You can use it to be on the safe side, when you don't know how your render array is processed.

For complex elements you need a render element. The method view() would generates this:

$row['email'] = $entity->email->view();

But this does not work. The problem seems to be in the custom entity. According to the error message there is a call to an undefined method render, which should be defined in MyEntity. Your entity does not know how to handle the email field.

If you don't want to theme the field, you can use the value as markup:

$row['email']['#markup'] = $entity->email->value;

Or you can put the field as an object:

$row['email'] = $entity->email;

Or you can build your own render array, for example as a link:

$row['title'] = array(
      '#type' => 'link',
      '#title' => $entity->label(),
      '#url' => $uri,
| improve this answer | |
  • The ID line actually works very well. It's the email line that doesn't. – Hendrik Nov 6 '15 at 21:42
  • That makes sense, the error is before the function returns the render array, in your custom entity is no method to render the entity. – 4k4 Nov 7 '15 at 8:17
  • I'm not sure I understand what you're saying. In my code, $entity->email->view() doesn't generate a render array, but an error message. – Hendrik Nov 7 '15 at 11:06
  • I don't think ListBuilder expects render arrays in buildRow(). For example, if I supply a number of static strings, such as $row[] = "Hello, World", the output is just fine. – Hendrik Nov 7 '15 at 11:08
  • According to documentation the function returns "A render array structure of fields for this entity", but when you check how it is used in core, there are examples, where strings are OK. I'll update my answer. – 4k4 Nov 7 '15 at 16:40

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.