Overview
Vue-based themes will soon be deprecated. Please switch to React-based themes, as all future updates and support will focus exclusively on React.
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>