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>