Skip to content

Latest commit

 

History

History
124 lines (88 loc) · 4.83 KB

SFC-Components.adoc

File metadata and controls

124 lines (88 loc) · 4.83 KB

Writing Single File Components

In this chapter we will be exploring how to go about implementing a new section component using the classic Vue single file components. We will demonstrate the process by referencing to an example project that you will see below.

You can see in the following picture that multiple components are displayed as unknown in our example project. These components have been created in First Spirit but in our pwa the UI has not been implemented yet.

Missing Teaser

By clicking on the question mark on one of the unknown components the dev info tells us all the information the component has access to. In our example we can see that there should be a component of type Section. We can also see that the 'sectionType' property of this missing section is called teaser.

Dev Mode Teaser

The section components in our demo project are located in ~/components/Section/. That’s where we are going to create a new file for the example component.

In general the ~/components folder holds all the reusable components in your project. You are free to create subfolders as you like and come up with a custom folder structure. Remember to update any references to your components accordingly.

We name our new file Teaser.vue and add a template tag to the file so that we can see something when we fire up the dev server:

<template>
  <div>
    <h1>Teaser Component</h1>
  </div>
</template>

Now we need to reference our newly created teaser component inside the general Section.vue component which can be found in the ~/components/PageBodyContent/ directory.

Add a teaser case to the computed sectionComponent property. Make sure to name the case after the respective sectionType and name the component that is going to be resolved according to the path where it is located.

In this case Section/Teaser.vue becomes SectionTeaser. As of now, the component name needs to be a hardcoded string. Variable component resolving is not yet possible in Nuxt 3.

// ~/components/PageBodyContent/Section.vue

...
const sectionComponent = computed(() => {
  switch (props.content.sectionType) {
    case "teaser":
      return resolveComponent("SectionTeaser");
    default:
      return resolveComponent("Unknown");
  }
});
...

When we go back to the browser, instead of the unknown component we now see our new teaser component.

Basic Teaser

Our component is recognized correctly. But we still do not display any data from the CaaS in our component. For that we hover over our new component and click on the appearing question mark on the right side again.

Available Properties

This shows us all the data available to display. In our example there is a property called st_jumbo_headline that we are going to display.

Our newly created Teaser.vue component has access to a data property that gets passed from the general Section component. You can provide some typesafety by adding a custom interface to this property.

To display data in our example we modify the Teaser.vue component like this:

<template>
  <div>
    <h1>Teaser Component: {{ data.st_jumbo_headline }}</h1>
  </div>
</template>

<script setup lang="ts">
interface Teaser {
  st_jumbo_headline:string
}
defineProps<{ data: Teaser }>();
</script>

The result should look like this:

Displayed Headline

To render richtext, image or button elements you can use the RichText.vue, Image.vue and Button.vue components which can be found under the ~/components/Elements/ folder. We use them like this in our example teaser component:

<template>
  <div>
    <h1>Teaser Component: {{ data.st_jumbo_headline }}</h1>
    <ElementsRichText :richtext="data.st_headline" />
    <ElementsImage :image="data.st_picture" :alt="data.st_picture_alt" />
    <ElementsButton :button="data.st_button" @button-click="clickHandler" />
  </div>
</template>

<script setup lang="ts">
import { Image, RichTextElement } from "fsxa-api";

interface Teaser {
  st_jumbo_headline:string
  st_headline: RichTextElement[];
  st_picture?: Image;
  st_picture_alt?: string;
  st_button: MyCustomButtonInterface
}
defineProps<{ data: Teaser }>();


function clickHandler(){
  // do sth.
}
</script>

Of course, you can modify all components and adjust them according to your specific requirements. In our implementation example ElementsButton emits a buttonClick event which can be hooked into with @button-click. Define your click handler function inside the script tag as shown above.