Rendering Custom Elements
The Drupal Custom Elements Connector module allows you to render custom elements in your Nuxt.js application fetched from a Drupal backend.
Basics
Generally, each custom element maps to a Vue component, which is automatically picked up when the component is named exactly like the custom element, e.g. for the element drupal-markup
create the component drupal-markup.vue
.
There is one gotcha though: For Vue to find your custom element components, they must be globally registered. Thus, in Nuxt, simply put them into your components/global
folder, and they are picked up.
Mapping attributes to props
Every attribute of a component is available in Vue's $attrs
variable. However, it's best practice to define the props for the component, what makes each attribute available under its defined name:
<template>
<div class="node">
<h2 v-if="title">Node: {{ title }}</h2>
</div>
</template>
<script setup lang="ts">
defineProps<{
title?: string;
}>()
</script>
Rendering slots
Rendering slots works differently depending on whether custom-elements are serialized into JSON or markup. In short, for rendering a slot in a Vue template, simply use the following snippet:
<template>
<slot name="body">
<component :is="useDrupalCe().renderCustomElements(body)" />
</slot>
</template>
<script setup lang="ts">
defineSlots<{
body(): any;
}>()
defineProps<{
body?: CustomElementContent;
}>()
</script>
This snippet works with both, JSON and markup serialization. The markup serialization uses the slot, while the fallback value of the slot takes care of rendering the JSON-serialized value received as prop.
JSON serialization (default)
Custom elements contained in slots get passed as JSON, which can be easily rendered with the helper provided by the nuxtjs-drupal-ce connector:
<template>
<component :is="useDrupalCe().renderCustomElements(body)" />
</template>
<script setup lang="ts">
defineProps<{
body?: CustomElementContent;
}>()
Note: When rendering via JSON content, the module supports default components.
Markup serialization
With markup, the Vue template compiler needs to be enabled:
// nuxt.config.js
export default {
vue: {
runtimeCompiler: true
}
}
Then, slots will be directly passed as Vue slots.
<slot name="body">Fallback content.</slot>
Full example
Here is an example of a component that leverages props and slots and works with both markup and JSON serialization:
<template>
<div class="node">
<h2 v-if="title">Node: {{ title }}</h2>
<slot name="body">
<component :is="useDrupalCe().renderCustomElements(body)" />
</slot>
</div>
</template>
<script setup lang="ts">
defineSlots<{
body(): any;
}>()
defineProps<{
title?: string;
body?: CustomElementContent;
}>()
</script>