{% raw %}
This document is intended to list predefined mustache tags, HTML classes and attributes, and JavaScript methods (functions) for layout rendering with ecomplus-store-render.
It's possible to use any HTML template for E-Com Plus storefront. After reading this documentation, you will be able to customize a theme (editing some elements only) or start a new theme from scratch.
If you want to create a new theme from scratch, be sure to follow this template structure.
E-Com Plus storefront uses Vue.js 2 framework, so store template specifications follow the Vue template syntax.
After reading the docs, visit the Wiki to make suggestions or contribute with documentation content and examples. If you need help, feel free to open a new issue.
Your HTML file must include Vue, storefront JS SDK and the layout renderer app. You can include storefront "all in one" JS file (recommended):
<script src="https://ecvol.com/js/storefront@2/storefront.min.js"></script>
Or import the scripts one by one (not recommended):
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ecomplus-sdk@1/dist/sdk.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ecomplus-render@2/dist/render.min.js"></script>
Then, start the layout rendering with JS below:
Ecom.init()
The scripts should be loaded after the HTML content of the page,
so you have to put them before </body>
tag,
we also recommend to load them before other scripts,
such as jQuery lib. Final example:
<body>
<!-- HTML content -->
<script src="https://ecvol.com/js/storefront@2/storefront.min.js"></script>
<script>
Ecom.init()
</script>
<!-- Optionally, other JS -->
</body>
You probably want to manipulate the rendered elements with JavaScript (maybe with jQuery), to work properly, you must do this after the renderization.
Send a callback function as first param of init method:
Ecom.init(function () {
// handle events and effects with rendered elements
})
HTML classes used by this library will be named with the prefix _ecom-
,
data attributes may be used together with the classes in the elements.
Your HTML must have an element
with class _ecom-store
, it's required.
All Vue template must be inside this element,
including all mustache tags and Vue HTML attributes,
so probably it will be the <body>
, but it's not a rule, you can use
a <div>
, <span>
or any other:
<body class="_ecom-store">
<!-- HTML CODE -->
</body>
By default, store will be defined in function of the site domain,
but you can also use the attributes data-store
and data-id
with your Store ID and Store Object ID respectively:
<div class="_ecom-store" data-store="100" data-id="5a674f224e0dcec2c3353d9d">
It's useful if the template is designed for one specific store only, or if you want to work with multiple stores in the same storefront.
If you don't want to use the store default language,
you can use the attribute data-lang
:
<div class="_ecom-store" data-lang="en_us">
Use lowercase letters and separate lang of country (if any) by underline,
eg.: pt_br
, en_us
, it
, es
.
Each HTML element with class _ecom-el
will be an
Vue instance.
It represents an object declaration, preceded of a REST API GET request.
Inside ._ecom-el
elements you can use mustache tags and any
Vue template
attributes.
Store API requests
are rendered from ._ecom-el
elements
with the attributes below:
Attribute | Description |
---|---|
data-type |
Type of object, with one of these values |
data-id |
API Object ID, the _id of the object you are getting from the API (optional) |
In almost all cases, you will not create an HTML for each object,
for example, you will create only one HTML file for all products,
not one per product.
In these cases it's not possible to specify data-id
(it's dynamic),
let the element without this attribute,
ID will be defined in function of page URL (slug).
The
instance data
will be an object with body
property, body
is the object returned from
Store API,
with the same properties.
Possible values for data-type
:
Type | Object model |
---|---|
product |
Reference |
brand |
Reference |
category |
Reference |
collection |
Reference |
customer |
Reference |
cart |
Reference |
order |
Reference |
application |
Reference |
store |
Reference |
The example below shows some of the current store information:
<div class="footer _ecom-el" data-type="store">
<div class="logo" v-if="body.logo">
<img v-bind:src="body.logo.url" v-bind:alt="body.logo.alt" v-bind:width="width(body.logo)">
</div>
<h2 class="store-title"> {{ body.name }} </h2>
<p> {{ body.description }} </p>
</div>
In the example above, Vue data (inside mustache tags and v-*
attributes) have the
properties listed here,
following the store object model, but only with public data.
The example below is a simple implementation of a product page:
<div class="_ecom-el" data-type="product">
<div v-bind:class="'prod-' + body.sku" v-if="body.visible">
<ul>
<li v-for="picture in body.pictures">
<span v-if="picture.big">
<img v-if="picture.zoom" v-bind:src="picture.big.url" v-bind:alt="picture.big.alt"
v-bind:data-zoom="picture.zoom.url" />
<img v-else v-bind:src="picture.big.url" v-bind:alt="picture.big.alt" />
</span>
</li>
</ul>
<a v-bind:href="body.slug">
<h1> {{ name() }} </h1>
</a>
<p class="price-block">
<span v-if="onPromotion()">
{{ body.currency_symbol }}
<strong class="price"> {{ formatMoney(body.price) }} </strong>
<span class="base-price"> {{ formatMoney(body.base_price) }} </span>
</span>
<span v-else>
{{ body.currency_symbol }} <strong class="price"> {{ formatMoney(price()) }} </strong>
</span>
</p>
<div v-if="body.available">
<button v-if="inStock()" class="buy"> Buy </button>
<div class="no-stock" v-else> Out of stock </div>
</div>
<div class="description">
{{ body.body_html }}
</div>
</div>
</div>
If you are creating the HTML file for a specific product only,
or embedding one product inside a custom page, you must set data-id
with the product ID:
<div class="_ecom-el" data-type="product" data-id="123a5432109876543210cdef">
Vue data (inside mustache tags and v-*
attributes) follows this
object reference.
Note that you can use similar code for other types of objects (API resources).
It's possible to render a list of Store API
categories,
brands or
collections,
to do that, you must add the attribute data-list-all
to the ._ecom-el
element.
This is available only for elements with one of following data-type
:
Type | Object model |
---|---|
brand |
Reference |
category |
Reference |
collection |
Reference |
The example below is a simple implementation of a list of categories, up to 1000 objects, with random order, using Vue list:
<ul class="_ecom-el" data-type="category" data-list-all="true">
<li v-for="category in body.result">
<a v-bind:href="category.slug">
{{ category.name }}
</a>
</li>
</ul>
By default, the objects are randomly ordered on the list,
if you want alphabetical order, you can use the alphabeticalSort
pre-built method:
<li v-for="category in alphabeticalSort(body.result)">
Search API requests
are rendered from ._ecom-el
elements
with the data-type
equal to items
or terms
,
and other attributes depending of search case.
The
Vue instance data
will be an object with body
property, body
is the object returned from
Search API,
with the same properties.
To list products, data-type
must be equal to items
.
You can get more info and example of returned object from
API reference.
The ._ecom-el
element must also have the following attributes:
Attribute | Description |
---|---|
data-type |
Equal to items |
data-term |
Searched keyword (optional) |
data-from |
Results offset number (optional) |
data-size |
Maximum number of results (optional) |
data-sort |
Results ordering, one of these enumered values (optional) |
data-ids |
Filter by specific products IDs separated by , (optional) |
data-brands |
Filter by list of brands IDs separated by , (optional) |
data-categories |
Filter by list of categories IDs separated by , (optional) |
data-price-min |
Filter by minimum price (optional) |
data-price-max |
Filter by maximum price (optional) |
data-spec-* |
Filter by product specification (optional) |
The example below is a simple implementation of a list of trending products, using Vue list:
<div class="row _ecom-el" data-type="items">
<div class="col-md-2" v-for="item in body.hits.hits">
<div v-if="item = item._source" class="item">
<div v-if="item.pictures && item.pictures[0] && item.pictures[0].normal" class="item-img">
<img v-bind:src="item.pictures[0].normal.url" v-bind:alt="item.pictures[0].normal.alt" />
</div>
<a v-bind:href="item.slug">
<h3> {{ name(item) }} </h3>
</a>
<p class="price-block">
<span v-if="onPromotion(item)">
{{ item.currency_symbol }}
<strong class="price"> {{ formatMoney(item.price) }} </strong>
<span class="base-price"> {{ formatMoney(item.base_price) }} </span>
</span>
<span v-else>
{{ item.currency_symbol }}
<strong class="price"> {{ formatMoney(price(item)) }} </strong>
</span>
</p>
<span v-if="item.available">
<button v-if="inStock(item)" class="buy"> Buy </button>
<span class="no-stock" v-else> Out of stock </span>
</span>
</div>
</div>
</div>
It's possible to specify the maximum number of listed items with data-size
,
the example below will list up to 12 most popular items:
<div class="_ecom-el" data-type="items" data-size="12">
For pagination, you should use data-from (offset) together with data-size (limit). The example below will list up to 12 items, starting from the 24º, so, from 24º to 36º:
<div class="_ecom-el" data-type="items" data-from="24" data-size="12">
By default, items will be ordered by popularity (number of page views),
but you can use custom sort with data-sort
attribute:
<div class="_ecom-el" data-type="items" data-sort="1">
It must have one of the number values below:
Enum | Description |
---|---|
1 |
Sort by sales, products that sells more appear first |
2 |
Sort by price ascending, products with lowest price appear first |
3 |
Sort by price descending, products with highest price appear first |
4 |
Sort by creation date, new products appear first |
To find products searching by name and/or keywords, you can use data-term
:
<div class="_ecom-el" data-type="items" data-term="tshirt">
Here you can check an complete example of store search engine implementation.
It's possible to filter the resultant items list by product specs,
adding attributes of type data-spec-*
, where the wildcard must be replaced
by the specification (property name):
<div class="_ecom-el" data-type="items" data-spec-colors="Blue" data-spec-size="M">
To list products from specific categories you should use
data-categories
attribute.
Following example will list items from one category only, but you can
specify more than one by separating categories IDs with ,
(comma):
<div class="_ecom-el" data-type="items" data-categories="f10000000000000000000001">
Similar to categories, you can list products from specific brands using
data-brands
attribute:
<div class="_ecom-el" data-type="items" data-brands="a10000000000000000000001">
You can also list specific items using the data-ids
attribute, where
you should put the IDs of respective products separated by comma:
<div class="_ecom-el" data-type="items" data-ids="1234567890abcdef01291510,1234567890abcdef01291511">
Note that you can combine the attributes from all above search and list examples to fit your needs.
To list products of a collection you have to use both Store API and Search API.
The notation is such as the example below:
<div class="_ecom-el" data-type="collection" data-id="c92000000000000000001111"
data-list="products" data-size="12">
<a v-bind:href="body.slug">
<h3 class="coll-name"> {{ body.name }} </h3>
</a>
<ul>
<li v-for="item in body.hits.hits">
<div v-if="item = item._source" class="item">
<div v-if="item.pictures && item.pictures[0] && item.pictures[0].normal" class="item-img">
<img v-bind:src="item.pictures[0].normal.url" v-bind:alt="item.pictures[0].normal.alt" />
</div>
<a v-bind:href="item.slug">
<h4> {{ name(item) }} </h4>
</a>
<p> SKU: {{ item.sku }} </p>
<p class="price-block">
<span v-if="onPromotion(item)">
{{ item.currency_symbol }}
<strong class="price"> {{ formatMoney(item.price) }} </strong>
<span class="base-price"> {{ formatMoney(item.base_price) }} </span>
</span>
<span v-else>
{{ item.currency_symbol }}
<strong class="price"> {{ formatMoney(price(item)) }} </strong>
</span>
</p>
<button v-if="inStock(item)" class="buy"> Buy </button>
<span class="no-stock" v-else> Out of stock </span>
</div>
</li>
</ul>
</div>
In these cases you must use data-type
and data-id
as expected
for a Store API object.
You also have to use the attribute data-list
with
value products
, by doing this, you will be listing the
collection products by IDs such as a Search API object.
In addition, you can use the other
attributes for a Search API items list,
such as the data-size
used in the above example.
After the renderization of each ._ecom-el
element,
the class rendered
is automatically added, to hide the non-rendered elements
we recommend to use the following styles:
._ecom-el {
opacity: 0;
}
._ecom-el.rendered {
opacity: 1;
}
If you want to use fade effect:
._ecom-el {
opacity: 0;
}
._ecom-el.rendered {
opacity: 1;
animation: fadein 1s;
-moz-animation: fadein 1s;
-webkit-animation: fadein 1s;
-o-animation: fadein 1s;
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Firefox */
@-moz-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Safari and Chrome */
@-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Opera */
@-o-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Of course you can change the animation time from 1s to what you want.
{% endraw %}