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 in Vue components works seamlessly with both JSON and markup serialization. Simply use native Vue slots in your template:
<template>
<slot name="body" />
</template>
<script setup lang="ts">
// Optional: Define slots for better TypeScript support
defineSlots<{
body(): any;
}>()
</script>
This works with both JSON and markup serialization. The Nuxt Drupal CE connector automatically handles the slot content in both cases.
JSON serialization (default)
With JSON-formatted custom elements, slot content is automatically mapped to Vue slots. You can use named slots or the default slot:
<template>
<div class="card">
<slot name="header" />
<slot />
<slot name="footer" />
</div>
</template>
<script setup lang="ts">
// Optional: Define slots for TypeScript
defineSlots<{
header(): any;
default(): any;
footer(): any;
}>()
</script>
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" />
</div>
</template>
<script setup lang="ts">
// Optional: Define slots for TypeScript
defineSlots<{
body(): any;
}>()
defineProps<{
title?: string;
}>()
</script>