Providing blocks
In order to provide blocks that render into custom elements, for example for using as part of the Layout Builder, the block cannot directly return a custom element object, since its interface requires a render array. Instead, simply return the custom element as render array via its helper toRenderArray(). When done so, the custom element is going to be picked up correctly when the layout is rendered.
Example block
/**
* Provides an example news listing block.
*
* @Block(
* id = "lupus_decoupled_drupal_example_news_listing",
* admin_label = @Translation("Example news listing"),
* category = @Translation("Custom")
* )
*/
class ExampleNewsListingBlock extends BlockBase {
/**
* {@inheritdoc}
*/
public function build() {
$articles[] = CustomElement::create('article-teaser')
->setAttribute('href', 'https://example.com/news/1')
->setAttribute('excerpt', 'The excerpt of the news entry.');
$articles[] = CustomElement::create('article-teaser')
->setAttribute('href', 'https://example.com/news/2')
->setAttribute('excerpt', 'The excerpt of another news entry.');
$teaser_listing = CustomElement::create('teaser-listing')
->setAttribute('title', 'Latest news')
->setAttribute('icon', 'news')
->setSlotFromNestedElements('default', $articles);
// Return the custom element as render array to fulfill the interface.
return $teaser_listing->toRenderArray();
}
}
Routes
The Lupus CE Renderer module takes care of rendering routes of the format custom_elements via Drupal's regular routing system. That means a route can be defined as usual in Drupal, additionally define the _format to be custom_elements:
Custom Element Processors
The custom elements module comes with Custom element processors that try to implement a reasonable default for content entities and fields. These defaults can be further customized with custom modules as needed.