1

I am working on a Drupal 8 module, and a separate module of examples, on how to use the first module. In my example module, I have a function in my controller that looks like this:

public function basicUsage() {
  // Basic line chart.
  $series[] = [
    'data' => [[0, 3], [4, 8], [8, 5], [9, 13]],
  ];
  $params = [
    "data" => $series,
    "theme" => "flot_examples_basic_usage",
  ];
  $flot = new FlotD8($params);
  $output[] = $flot->outputPlot();
  return $output;
}

I would like to use the standard entity notation if possible to simplify things, and make it look like this:

public function basicUsage() {
  // Basic line chart.
  $series[] = [
    'data' => [[0, 3], [4, 8], [8, 5], [9, 13]],
  ];
  $output["flot_d8"] = [  //maybe name needs to be FlotD8?
    "#data" => $series,
    "#theme" => "flot_examples_basic_usage",
  ];

  return $output;
}

Here is the code for my class. What do I need to do or change to give it the behavior I'm looking for? Is it just a matter of extending a certain Core Entity class? I do not need any schema or database functionality.

<?php
namespace Drupal\flot_d8\Entity;
class FlotD8 {
  protected $id;
  protected $theme;
  protected $data;
  protected $options;

  function __construct($params){
    $this->id = isset($params['id']) ? $params['id'] : 'placeholder';
    $this->theme = isset($params['theme']) ? $params['theme'] : 'flot_d8_my_template';
    $this->data = $params['data'];
    $this->options = isset($params['options']) ? $params['options'] : NULL;
  }

  /*
   * Create the theme output.
   */
  function outputPlot (){
    $drupalsettings['flot_d8'][$this->id] = ['data' => $this->data, 'options' => $this->options];
    $output = [
      '#attached' => [
        'drupalSettings' => $drupalsettings,
      ],
      '#theme' => $this->theme,
      '#options' => $this->options,
      '#data' => $this->data,
    ];
    return $output;
  }
}
5
  • You would need to make the entity discoverable via annotation, but I think after that you probably do not want to make this a content entity OR a config entity. You could extend EntityInterface if you have ids and what not. Or perhaps make this a Data Type via Typed Data API?
    – mradcliffe
    Feb 4, 2016 at 16:32
  • I'm newish to Drupal, and very new to D8. Would the Typed Data API be trivial to interface with, or, given the simplicity of my example, do you think I should keep it as-is? Feb 4, 2016 at 16:36
  • You should create a custom render element for your plot.
    – Eyal
    Feb 4, 2016 at 22:00
  • @Eyal, I already have a twig template, js, and css files to draw the plot on the screen, given the data passed to this FlotD8 object. Does a custom render element entail doing more, above and beyond this? If so, are there any good Drupal 8 tutorials on this? Feb 4, 2016 at 23:11
  • I can see @berdir have you a full answer about render arrays. Good luck.
    – Eyal
    Feb 5, 2016 at 9:03

1 Answer 1

2

Why exactly do you want to use an entity?

Entities are about CRUD. Saving, loading and deleting data in the database or somewhere else.

From looking at your code, that doesn't really seem to be what you're after, you just have an API to display some data. That's not what entities are about at all.

You could make a service of your class but that doesn't really seem to match either.

I guess the only thing that would make sense is to define it as a render element. See RenderElement and Render API overview.

So you'd define your class with @RenderElement in an Element namespace, see Link for an example. You give it a name in the annotation, like yourmodule_plot and in your render array, reference it as #type => 'yourmodule_plot' and pass the data to it like that.

A render element class basically consists of a getInfo() method that defines some default properties. In your case, that would be #theme, #attached and so on. if you need to dynamically process your data, you can add a #pre_render callback like shown in the Link example that can then process the merged array of your defaults + data you specify in the controller.

3
  • I posted a question several weeks ago about this module and someone suggested that making it an entity would help with what I wanted to do. I followed up with a a question and said that I didn't need to save or load anything, but didn't receive a response, or any other answers from anyone else. Thanks for your insight! Feb 5, 2016 at 0:23
  • Note that render elements like that are nice when you do something similar many times (like displaying a table, link, ...), then you can avoid code duplication. If it's something you'll only do once then it's just overhead. It can't do anything that you couldn't also just directly specify in your render array, you can also have methods on your controller if you want to avoid long methods. But I guess it is a useful skill to learn, it's just an example module as I understood.
    – Berdir
    Feb 5, 2016 at 16:14
  • This is EXACTLY what i was wanting...thank you! I'm working on making a Drupal 8 wrapper for a javascript plotting library. With this render element, an end user can create an array of chart options, an array of data, and the render element can determine which js files to include, what needs to be added to drupalSettings, and then call a twig template if necessary. Feb 5, 2016 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.