Custom elements
Creating custom elements
The CustomElement
class helps modelling a tree of custom elements. The class provides an API for creating and nesting custom elements as shown the following example:
<?php
use \Drupal\custom_elements\CustomElement;
class NewsController extends ControllerBase {
public function buildNewsListing() {
$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.');
return CustomElement::create('teaser-listing')
->setSlotFromNestedElements('default', $articles);
}
}
This creates:
<teaser-listing title="Latest news" icon="news">
<article-teaser
href="https://example.com/news/1"
excerpt="The excerpt of the news entry."
>
</article-teaser>
<article-teaser
href="https://example.com/news/2"
excerpt="The excerpt of another news entry."
>
</article-teaser>
</teaser-listing>
Slots
Slots are used for passing nested, arbitrary content. Slots are named and can have one or multiple child elements. The child elements keep their ordering, unless a custom weight is passed. The default
slot is a special slot name, which is used for nested markup without a given slot-name, e.g. <the-element>some-nested-content</the-element>
, which is the same as <the-element><slot name="default">some-nested-content</slot></the-element>
.
Attributes
Besides slot, an element may contain any number of attributes, which are key value pairs. Attribute values can be scalars and arrays, which - when rendered into markup format - become a JSON-encoded string.
Cache Metadata
Custom elements integrate with Drupal's cache API, thus allows element to define their caching dependencies via cache tags and their cache context. It implements the CacheableDependencyInterface
, so it's cache dependencies can be easily added as usual, for example entities:
<?php
$custom_element->addCacheableDependency($entity);
?>
When a tree of elements is rendered, cache metadata of individual elements is aggregated and bubbled up to the page, just as with Drupal's traditional render system.
API documentation
For detailed API documentation please refer to the in-code API documentation of the \Drupal\custom_elements\CustomElement
class.
Rendering into custom elements
For rendering entities, and more generally any kind of data, into custom elements, the module provides the custom element generator service:
<?php
class SomeClass {
use CustomElementGeneratorTrait;
public function someMethod() {
$custom_element = $this->getCustomElementGenerator()
->generate($entity, $view_mode);
}
}
This will render into custom elements as configured for the entity. Refer to Customized API output for an overview.
For other kind of data, for some field items, the data may be processed via "automatic processing" which makes use of custom element processors:
<?php
class SomeClass {
use CustomElementGeneratorTrait;
public function someMethod() {
$element = CustomElement::create('some-element');
$this->getCustomElementGenerator()
->process($items, $element, $view_mode);
}
}
Serializing to markup or JSON
A tree of custom elements can be output in markup
or JSON
format:
Serializing to JSON
For serializing a tree of custom elements into JSON make use of the provided normalizer:
<?php
$custom_element_normalizer = \Drupal::service('custom_elements.normalizer');
$bubbleable_metadata = BubbleableMetadata::createFromObject($custom_element);
$json = $custom_element_normalizer->normalize($custom_element, NULL, ['cache_metadata' => $bubbleable_metadata]);
Serializing to markup
For generating markup for a tree of custom elements, simply render it via the Drupal's traditional render API:
<?php
$render = $custom_element->toRenderArray();
$renderer = \Drupal::service('renderer');
$markup = $renderer->renderRoot($customElement);
?>
Custom Element markup styles
Custom elements use "slots" for handling content distribution, i.e. for passing nested content to an element. However, the concrete syntax used for handling slots may differ by various frameworks. Thus, the module supports rendering to different markup styles while it defaults to the Web component style syntax. In addition, the module supports the Vue2 and Vue 3 syntax which can be enabled via config:
drush config:set custom_elements.settings markup_style vue-3
Traditional render arrays
Custom elements may be rendered using Drupal's traditional render API:
<?php
$render[] = $custom_element->toRenderArray();
?>
On the other hand, it's possible to wrap a traditional render array into a custom element:
<?php
$custom_element = CustomElement::createFromRenderArray($render_array);
?>
The resulting element can be further customized, but by default it simply renders the $render_array
and wraps it into a <drupal-markup>
element, that the frontend may simply output.