SR
Click to open github profile
Usage

Connect Components

Learn how to integrate Craft CMS data with your Nuxt components


This guide explains the steps to connect your Vue components with data from Craft CMS. We’ll set up a catch-all route, create a mapping object for components, query data, and use the <CraftPage/> and <CraftArea/> components to display content dynamically.

Catch all route

To support dynamic URLs in your Nuxt app, add a catch-all route by creating a file named ~/pages/[...slug].vue. This route will capture all URLs and allow you to dynamically render the corresponding content.

Mapping Object

Define a mapping object in the ~/pages/[...slug].vue file. This object connects each Craft CMS section handle to a Vue page component and each field handle to a specific Vue component. This setup allows the correct component to render based on the Craft CMS data.

For example:

<script setup lang="ts">
  import type { Config } from 'vue-craftcms'
  import Home from '~/templates/pages/home.vue'
  import News from '~/templates/pages/news.vue'

  import ImageText from '~/templates/components/imageText.vue'
  import Headline from '~/templates/components/headline.vue'

  const mapping: Config = {
    pages: {
      home: Home, // 'home' is the section handle of the Craft CMS section, 'Home' is the Vue component.
      news: News,
    },
    components: {
      imageText: ImageText,
      headline: Headline,
    },
  }
</script>

Working with Entry Types

When enableEntryTypeMapping is set to true in your nuxt.config.ts, you can link your Craft entries using the format sectionHandle:entryTypeHandle.

If the entry type handle is default or matches the section handle, you don’t need to explicitly define the :entryTypeHandle.

const mapping: Config = {
  pages: {
    home: Home, // equivalent to home:default or home:home
    'news:default': News, // equivalent to news or news:news
    'news:reference': News, // section handle = news, entry type handle = reference
  },
  components: {
    // additional components
  },
};

Query Data

Use the useCraftQuery() composable to fetch data from Craft CMS. Combine this with Nuxt’s useRoute() composable to get the correct URI based on the route parameters.

Here’s what you can add the code to [...slug].vue:

const route = useRoute()
const uri = route.params.slug.length > 0 ? route.params.slug : '__home__'
const { data, error } = await useCraftQuery('entries').uri(uri).one()

if (error.value) {
  console.error(error.value)
}

console.log(data.value)

Display Page

To display the page data, use the <CraftPage/> component in [...slug].vue. This component automatically renders defined pages based on the mapping configuration and data received from Craft CMS.

Tip

To find out more about the <CraftPage/> check out the docs.

Here’s what a full example file might look like:

<script setup lang="ts">
  import { CraftNotImplemented, type Config } from 'vue-craftcms'
  import Home from '~/templates/pages/home.vue';
  import News from '~/templates/pages/news.vue';

  import Headline from '~/templates/components/headline.vue'

  const mapping: Config = {
    pages: {
      'home': Home,
      'news': News,
    },
    components: {
      'block_imageText': CraftNotImplemented,
      'block_headline': Headline,
    }
  };

  const route = useRoute()
  const uri = route.params.slug.length > 0 ? route.params.slug : '__home__';
  const { data, error } = await useCraftQuery('entries').uri(uri).one()

  if(error.value) {
    console.error(error.value)
  }

  console.log(data.value)
</script>

<template>
  <div>
    <CraftPage v-if="data" :config="mapping" :content="data" />
  </div>
</template>

This setup should render the correct Nuxt page based on the Craft CMS section handle.

To verify the data structure Craft CMS sends to your page, you can add the following code to inspect the data in home.vue:

templates/pages/home.vue
<template>
  <h1>Home</h1>
  <pre>
    {{ $attrs }}
  </pre>
</template>

Display Components

To connect Matrix blocks with Vue components, use the <CraftArea/> component. This component will dynamically render Vue components based on the content provided from Craft CMS.

Example:

templates/pages/home.vue
<script setup lang="ts">
  const props = defineProps({
    metadata: {
      type: Object,
      required: true,
    },
    contentBuilder: {
      type: Object,
      required: true,
    },
    sectionHandle: {
      type: String,
      required: true,
    },
    title: {
      type: String,
      required: true,
    },
  });
</script>

<template>
  <div>
    <h1>{{ props.title }}</h1>
    <CraftArea v-if="props.contentBuilder" :content="props.contentBuilder" />
  </div>
</template>
Tip

To find out more about the <CraftArea/> check out the docs.


Copyright © 2024 Samuel Reichör