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>