Skip to content
On this page

Custom Elements (CMS)

WARNING

This tutorial is a continuation of example from the backend part. That can be found here

All custom CMS elements created in the backend require corresponding implementations in the frontend application.

The CMS package utilizes the resolveComponent method from Vue to identify the component returned by the backend API. Therefore, the only requirement is to globally register the component with the appropriate name.

Registration

Demo store

The demo store utilizes Nuxt 3, which by default registers all components globally. For optimal application structure, we recommend adding the components to the /components/cms directory.

Vue apps

Global registration in Vue apps

ts
import CmsBlockCustomBlock from "./components/cms/CmsElementDailymotion.vue";

app.component("CmsElementDailymotion", CmsBlockCustomBlock);

Naming

The component is searched in the global component register by its name.

Resolving component in CMS package

js
const componentNameToResolve = pascalCase(`Cms-${type}-${componentName}`);
const resolvedComponent = resolveComponent(componentNameToResolve);

Component name must be the same as it was registered in the backed.

ts
Shopware.Service('cmsService').registerCmsElement({
    ...
    name: 'dailymotion',
    ...
});

Lets create new component components/cms/element/CmsElementDailymotion.vue

vue
// components/cms/element/CmsElementDailymotion.vue
<script setup lang="ts">
import type { Schemas } from "#showpare";

type CmsElementDailymotion = Schemas["CmsSlot"] & {
  type: "dailymotion" | typeof String;
  slot: typeof String;
  config: CmsElementDailymotionConfig;
  translated: {
    config: CmsElementDailymotionConfig;
  };
};

type CmsElementDailymotionConfig = {
  dailyUrl: {
    value: string;
    source: "static";
  };
};
const props = defineProps<{
  content: CmsElementDailymotion;
}>();
</script>

<template>
  <div>
    <h2>Element!</h2>
    <div class="sw-cms-el-dailymotion">
      <div class="sw-cms-el-dailymotion-iframe-wrapper">
        <iframe
          frameborder="0"
          type="text/html"
          width="100%"
          height="100%"
          :src="props.content.config.dailyUrl.value"
        >
        </iframe>
      </div>
    </div>
  </div>
</template>

Reading config

Component settings are passed via props. The declared defaultConfig can be accessed through the props.content.config property.

The following is an example of how to convert the backend registration config to a TypeScript type.

ts
Shopware.Service('cmsService').registerCmsElement({
  ...
    name: 'dailymotion',
    defaultConfig: {
        dailyUrl: {
            source: 'static',
            value: ''
        }
    }
  ...
});
ts
type CmsElementDailymotionConfig = {
  dailyUrl: {
    value: string;
    source: "static";
  };
};
Custom Elements (CMS) has loaded