Skip to main content

Overview

Sections are reusable UI components that can be customized by merchants. Section files are present inside the sections folder of a theme.

Anatomy of a section

Sections also are Vue components & hence have a template, script & style tag. These are self-explanatory. A section component has access to $apiSDK object that is a handler for the application SDK client. It can use this object to fetch or update data. Each section also has a prop called settings. The prop value for this object is generated by evaluating the settings schema. This schema is defined inside the <settings> tag.

Example

Below is an example section for showing handpicked products

theme/templates/pages/wishlist.vue
<template>
<div :*className*="{
'section-main-container': !settings.props.full_width.value,
'full-width-section': settings.props.full_width.value,
}">

<h1 *className*="section-heading" *v-if*="settings && settings.props.heading.value">
{{ settings.props.heading.value }}
</h1>
<div className="products" v-if="products.length > 0">
<product-card
*v-for*="(product, index) in products"
:*key*="index"
:product="product"
/>
</div>
</div>
</template>

<settings>
{
"name": "featuredProducts",
"label": "Featured Products",
"props": [
{
"type": "text",
"id": "heading",
"default": "Featured Products",
"label": "Section Heading"
},
{
"type": "checkbox",
"id": "full_width",
"default": false,
"label": "Full width",
"info": "Check to allow items to take the entire width of the viewport"
}
],
"blocks": [
{
"type": "product",
"name": "Product",
"props": [
{
"type": "product",
"id": "product",
"label": "Select a Product",
"info": "Product Item to be displayed"
}
]
}
]
}

</settings>


<script>

import productCard from "@/components/product-card.vue";

export default {
props: ["settings", "apiSDK", "serverProps"],
components: {
"product-card": productCard
},
data: function () {
return {
products: this.serverProps || [],
};
},
initializeServerProps({ apiSDK, settings }) {
const products =
settings?.blocks?.map((b) => {
return b?.props?.product?.value;
}) || [];
return Promise.all(
products.map((slug) => {
return apiSDK.catalog.getProductDetailBySlug({
slug,
});
})
)
.then((results) => {
return results;
})
.catch((e) => console.log);
},
mounted() {
if(!this.products) {
this.fetchProducts()
}
},
methods: {
fetchProducts() {
const productSlugs =
this.settings?.blocks?.map((b) => {
return b?.props?.product?.value;
}) || [];
const promiseArr = productSlugs.map(slug => *this*.$apiSDK.catalog.getProductDetailBySlug({
slug
});
Promise.all(promiseArr)
.then((results) => {
this.products = results;
})
.catch((e) => console.log);
}
}
}

</script>

<style lang="less" scoped>
.section-main-container {
width: 80%
}
.full-width-section {
width: 100%
}

.section-heading {
margin: 10px 0
}

.products {
display: flex;
flex-wrap: wrap;
}
</style>