2

My goal is create a custom block that uses a twig template that you can pass info to via the theme function like so.

  public function build() {
    return array(
      '#type' => 'markup',
      '#markup' => $this->siteContent(),
    );
  }

  public function siteContent() {

    $source_text = some_function_returning_html_from_user();

    return array(
      '#theme' => 'scadfashblock',
      '#source_text' => $source_text,
    );
  }

I got the above code from a tutorial trying to render a template file for a custom page. The problem is this code throws an error saying that an array can't be returned this way, it must be a string.

I even tried doing it the drupal 7 way...

  public function build() {
    return array(
      '#type' => 'markup',
      '#markup' => $this->siteContent(),
    );
  }

  private function siteContent() {

    $output = array();
    $output['source_text'] = some_function_returning_html_from_user();

    return theme('scadfashblock', $output);
  }

This throws an error:

Call to undefined function Drupal\<module>\Plugin\Block\theme()

5

The markup render #type takes a string for its #markup element property, not a render array. However you do not need to wrap your custom theme/template with the markup type.

  public function build() {
    return array(
      '#theme' => 'scadfashblock',
      '#source_text' => $this->siteContent(),
    );
  }

  public function siteContent() {
    return some_function_returning_html_from_user();
  }

Then implement scadfashblock in hook_theme, provide a template_preprocess_scadfashblock and a templates/scadfashblock.html.twig with your markup.

1

First you implement Hook_theme like in D7

function preosasde_theme($existing, $type, $theme, $path) {
  return array(
      'similar_readings' => array(
          'variables' => array('readings' => NULL),
      )
  );
}

Then you create a render array that specifies the theme and the necessary variables as build() of your block:

foreach ($similar as $id => $data) {
      $sims[] = array('title' => $data['title'],
          'modified' => $data['date'], 'url' => $library->getAsdeUrl($id));
    }
return ['#theme' => 'similar_readings', '#readings' => $sims];

And finally you define a template in your module (or theme)

/templates/similar-readings.html.twig:

<table class='table table-striped table-condensed'>
                <tr><th>Datum</th><th>Titel</th></tr>
            {% if readings|length > 0 %}        
              {% for artikel in readings %} 
                <tr>
                        <td>{{ artikel.modified|date("d.m.Y") }}</td>
                        <td><a href="/{{ artikel.url }}">{{ artikel.title }}</a></td>
                </tr>
              {% endfor %}
            {% else %}
                <tr><td colspan="2"><em>keine</em></td></tr>
            {% endif %}
 </table>

You don't need the hook_preprocess anymore. But don't forget to clear the cache!

1

You are getting Call to undefined function Drupal\<module>\Plugin\Block\theme() simply because you are using theme() without qualifying it with its namespace; since that code is in a file using a namespace, PHP things you are using a function in the same namespace. If Drupal still had theme() as function, in that file you should call it as \theme(), but since that function doesn't exist in Drupal 8, you need to change the code you are using.

Calling a theme function is not different from what you would do in Drupal 7 when using a render array.

  public function build() {
    return [
      '#theme' => 'scadfashblock',
      '#source_text' => $this->siteContent(),
    );
  }

  private function siteContent() {
    // Add your code to populate source_text.
  }

See also theme() renamed to _theme() and should not be called directly, where it is explained that Drupal 8 modules should not use theme().

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.