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 sectionSections 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.
#
ExampleBelow is an example section for showing handpicked products
<template> <div :*class*="{ 'section-main-container': !settings.props.full_width.value, 'full-width-section': settings.props.full_width.value, }"> <h1 *class*="section-heading" *v-if*="settings && settings.props.heading.value"> {{ settings.props.heading.value }} </h1> <div class="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>