Stencil Utils Reference
On this Page
Stencil Utils is a utility library that contains the BigCommerce Stencil Events system and other functions that make building a theme with the Stencil framework a breeze.
These functions help you set up asynchronous requests to modify the customer’s cart or storefront view. By using this abstraction library, you can gain more-granular control over themes’ presentation. Use stencil-utils to:
- Interact with the cart
- Use
getPage
to return a template file.
Installing
As an ES6 module
- Run
npm install @bigcommerce/stencil-utils
to install the latest tagged version of stencil-utils for use with your theme. - Import the library
import utils from 'bigcommerce/stencil-utils';
in modules that depend on it.
Standalone
If you do not want to support ES6 modules, Stencil Utils can be included as a normal script:
- Copy the bundled script from
dist/stencil-utils.min.js
to your theme. - Include the script in your HTML document
- Access stencil utils from
window.stencilUtils
api.js
getPage
Request a page using Ajax.
utils.api.getPage(url, options, callback)
Argument | Type | Description/Usage |
---|---|---|
url | String | request URL (ex: `/cart.php`) |
options | Object | Can contain template , FormData (for POST methods), params (for GET methods), and/or config .
The template option allows you to select a particular template, or an array of templates, for rendering one page. Each value must correspond to a file present in the theme's templates/components/ subdirectory.
The `config` option can be used to pass extra resources, corresponding to attributes that are valid in a page's front matter, as an object.
|
callback | Function | Asynchronous function call to handle the results |
The config
argument works like front matter: it encapsulates JSON. For a usage example of config
, see the Remote API Example.
getPage Example
In the following example (from common/faceted-search.js
), api.getPage()
is called to help execute an updateView()
function:
updateView() {
$(this.options.blockerSelector).show();
api.getPage(urlUtils.getUrl(), this.requestOptions, (err, content) => {
$(this.options.blockerSelector).hide();
if (err) {
throw new Error(err);
}
// Refresh view with new content
this.refreshView(content);
});
}
Usage in Cornerstone
Cart API
The following functions allow your theme to work with cart contents in customized ways.
getCart
Argument | Type | Description |
---|---|---|
options | object | Return product variant options |
callback | Function | Asynchronous function call to handle the results |
getCart Example
utils.api.cart.getCart()
utils.api.cart.getCart({}, (err, response) => {
console.log(response);
console.log(err);
});
utils.api.cart.getCart({includeOptions: true}, (err, response) => {
console.log(response);
console.log(err);
});
getCartQuantity
Get a sum of the cart line item quantities.
utils.api.cart.getCartQuantity()
Argument | Type | Description |
---|---|---|
options | object | Return product variant options |
callback | Function | Asynchronous function call to handle the results |
getCartQuantity Example
utils.api.cart.getCartQuantity({}, (err, response) => {
console.log(response);
console.log(err);
});
utils.api.cart.getCartQuantity({}, (err, response) => {
console.log(response);
console.log(err);
});
Usage in Cornerstone
itemAdd
The itemAdd
function allows your code to add an item to the cart, with options:
utils.api.cart.itemAdd(FormData, callback)
Argument | Type | Description/Usage |
---|---|---|
formData | FormData object | Contains all details about the added item and its product options |
callback | Function | Asynchronous function call to handle the results |
itemAdd Example
itemAdd
is called at the head of the following example (from common/product-details.js
) to populate the cart:
utils.api.cart.itemAdd(this.filterEmptyFilesFromForm(new FormData(form)), (err, response) => {
const errorMessage = err || response.data.error;
$addToCartBtn
.val(originalBtnVal)
.prop('disabled', false);
this.$overlay.hide();
// Guard statement
if (errorMessage) {
// Strip the HTML from the error message
const tmp = document.createElement('DIV');
tmp.innerHTML = errorMessage;
return showAlertModal(tmp.textContent || tmp.innerText);
}
// Open preview modal and update content
if (this.previewModal) {
this.previewModal.open();
this.updateCartContent(this.previewModal, response.data.cart_item.id);
} else {
this.$overlay.show();
// if no modal, redirect to the cart page
this.redirectTo(response.data.cart_item.cart_url || this.context.urls.cart);
}
});
}
Usage in Cornerstone
itemUpdate
The itemUpdate
function allows your code to update a specified cart item’s quantity:
utils.api.cart.itemUpdate(itemId, qty, callback)
Argument | Type | Description/Usage |
---|---|---|
itemId | String | The item’s ID |
qty | Integer | The item’s quantity in the cart |
callback | Function | Asynchronous function call to handle the results |
itemUpdate Example
cartUpdate($target) {
const itemId = $target.data('cartItemid');
const $el = $(`#qty-${itemId}`);
const oldQty = parseInt($el.val(), 10);
const maxQty = parseInt($el.data('quantityMax'), 10);
const minQty = parseInt($el.data('quantityMin'), 10);
const minError = $el.data('quantityMinError');
const maxError = $el.data('quantityMaxError');
const newQty = $target.data('action') === 'inc' ? oldQty + 1 : oldQty - 1;
// Does not quality for min/max quantity
if (newQty < minQty) {
return swal({
text: minError,
type: 'error',
});
} else if (maxQty > 0 && newQty > maxQty) {
return swal({
text: maxError,
type: 'error',
});
}
this.$overlay.show();
utils.api.cart.itemUpdate(itemId, newQty, (err, response) => {
this.$overlay.hide();
if (response.data.status === 'succeed') {
// if the quantity is changed "1" from "0", we have to remove the row.
const remove = (newQty === 0);
this.refreshContent(remove);
} else {
$el.val(oldQty);
swal({
text: response.data.errors.join('\n'),
type: 'error',
});
}
});
}
Usage in Cornerstone
itemRemove
The itemRemove
function allows your code to remove items from the cart:
utils.api.cart.itemRemove(itemId, callback)
Argument | Type | Description/Usage |
---|---|---|
itemId | String | The item’s ID |
callback | Function | Asynchronous function call to handle the results |
itemRemove Example
In the following example (from cart.js
), itemRemove
is called before the if/else test:
cartRemoveItem(itemId) {
this.$overlay.show();
utils.api.cart.itemRemove(itemId, (err, response) => {
if (response.data.status === 'succeed') {
this.refreshContent(true);
} else {
alert(response.data.errors.join('\n'));
}
});
}
Usage in Cornerstone
update
The update
function allows your code to update the set of items in the cart:
utils.api.cart.update(itemId, qty, callback)
Argument | Type | Description/Usage |
---|---|---|
items | Array | The items in the cart |
callback | Function | Asynchronous function call to handle the results |
update Example
The following example shows a call to update
within the itemUpdate
function:
itemUpdate(itemId, qty, callback) {
let callbackArg = callback;
let items;
if (Array.isArray(itemId) && typeof qty === 'function') {
callbackArg = qty;
items = itemId;
} else {
items = [
{
id: itemId,
quantity: qty,
},
];
}
this.update(items, (err, response) => {
const emitData = {
items,
err,
response,
};
Hooks.emit('cart-item-update-remote', emitData);
callbackArg(err, response);
});
}
getItemGiftWrappingOptions
The getItemGiftWrappingOptions
function allows your code to retrieve gift-wrapping options for the current cart item, in customized ways:
utils.api.cart.getItemGiftWrappingOptions(itemId, callback)
Argument | Type | Description/Usage |
---|---|---|
itemId | String | The cart item |
callback | Function | Asynchronous function call to handle the results |
getItemGiftWrappingOptions Example
The following example (from cart.js
) calls getItemGiftWrappingOptions
to display gift-wrapping options in a modal:
bindGiftWrappingEvents() {
const modal = defaultModal();
$('[data-item-giftwrap]').on('click', event => {
const itemId = $(event.currentTarget).data('itemGiftwrap');
const options = {
template: 'cart/modals/gift-wrapping-form',
};
event.preventDefault();
modal.open();
utils.api.cart.getItemGiftWrappingOptions(itemId, options, (err, response) => {
modal.updateContent(response.content);
this.bindGiftWrappingForm();
});
});
}
Usage in Cornerstone
submitItemGiftWrappingOption
The submitItemGiftWrappingOption
function allows your code to handle the customer’s gift-wrapping selection for the current cart item:
utils.api.cart.submitItemGiftWrappingOption(itemId, qty, callback)
Argument | Type | Description/Usage |
---|---|---|
itemId | String | The cart item |
callback | Function | Asynchronous function call to handle the results |
submitItemGiftWrappingOption Example
This commented example shows a simple call to submitItemGiftWrappingOption
:
/**
* Submit giftwrapping options
*
* @param {String} itemId
* @param {Function} callback
*/
submitItemGiftWrappingOption(itemId, params, callback) {
this.remoteRequest(`/gift-wrapping/${itemId}`, 'POST', { params }, callback);
}
getContent
The getContent
function allows your code to display the cart contents in customized ways:
utils.api.cart.getContent(options, callback)
Argument | Type | Description/Usage |
---|---|---|
options | Object | Template containing content and totals children |
callback | Function | Asynchronous function call to handle the results |
getContent Examples
This example (from cart.js
) shows a call to getContent
within the refreshContent
function:
refreshContent(remove) {
const $cartItemsRows = $('[data-item-row]', this.$cartContent);
const $cartPageTitle = $('[data-cart-page-title]');
const options = {
template: {
content: 'cart/content',
totals: 'cart/totals',
pageTitle: 'cart/page-title',
statusMessages: 'cart/status-messages',
},
};
this.$overlay.show();
// Remove last item from cart? Reload
if (remove && $cartItemsRows.length === 1) {
return window.location.reload();
}
utils.api.cart.getContent(options, (err, response) => {
this.$cartContent.html(response.content);
this.$cartTotals.html(response.totals);
this.$cartMessages.html(response.statusMessages);
$cartPageTitle.replaceWith(response.pageTitle);
this.bindEvents();
this.$overlay.hide();
const quantity = $('[data-cart-quantity]', this.$cartContent).data('cart-quantity') || 0;
$('body').trigger('cart-quantity-update', quantity);
});
}
Usage in Cornerstone
assets/js/theme/global/cart-preview.js
assets/js/theme/cart.js
assets/js/theme/common/product-details.js
getShippingQuotes
The getShippingQuotes
function allows your code to retrieve shipping-cost quotes for the cart’s contents. It returns shippingQuote
objects that contain IDs. You must follow getShippingQuotes
by calling submitShippingQuote
on a quoteId
:
utils.api.cart.getShippingQuotes(params, renderWith, callback)
Argument | Type | Description/Usage |
---|---|---|
params | Object | Contains country_id, state_id, and zip_code |
template | String/Array/Object | The template to use for rendering |
callback | Function | Asynchronous function call to handle the results |
See submitShippingQutoes for an example.
Usage in Cornerstone
submitShippingQuote
The submitShippingQuote
function must be called after getShippingQuote
, which returns shippingQuote
objects that contain IDs. The cart page renders the shipping quotes. When the user selects one of the quotes, this function sends that quoteId
to the backend:
utils.api.cart.submitShippingQuote(quoteId, callback)
Argument | Type | Description/Usage |
---|---|---|
quoteId | Number | ID for a shipping quote returned by getShippingQuotes |
callback | Function | Asynchronous function call to handle the results |
getShippingQuotes and submitShippingQuote Example
The following example from cart/shipping-estimator.js
shows calls to both getShippingQuotes
and submitShippingQuote
:
bindEstimatorEvents() {
const $estimatorContainer = $('.shipping-estimator');
const $estimatorForm = $('.estimator-form');
$estimatorForm.on('submit', (event) => {
const params = {
country_id: $('[name="shipping-country"]', $estimatorForm).val(),
state_id: $('[name="shipping-state"]', $estimatorForm).val(),
city: $('[name="shipping-city"]', $estimatorForm).val(),
zip_code: $('[name="shipping-zip"]', $estimatorForm).val(),
};
event.preventDefault();
utils.api.cart.getShippingQuotes(params, 'cart/shipping-quotes', (err, response) => {
$('.shipping-quotes').html(response.content);
// bind the select button
$('.select-shipping-quote').on('click', (clickEvent) => {
const quoteId = $('.shipping-quote:checked').val();
clickEvent.preventDefault();
utils.api.cart.submitShippingQuote(quoteId, () => {
location.reload();
});
});
});
});
Usage in Cornerstone
applyCode
The applyCode
function applies a coupon code or gift certificate to the cart:
utils.api.cart.applyCode(code, callback)
Argument | Type | Description/Usage |
---|---|---|
code | String | Alphanumeric representation of the coupon or gift-certificate code |
callback | Function | Asynchronous function call to handle the results |
In the following example from cart.js
, applyCode
is called before the final if/else test to apply a coupon code:
bindPromoCodeEvents() {
const $couponContainer = $('.coupon-code');
const $couponForm = $('.coupon-form');
const $codeInput = $('[name="couponcode"]', $couponForm);
$('.coupon-code-add').on('click', (event) => {
event.preventDefault();
$(event.currentTarget).hide();
$couponContainer.show();
$('.coupon-code-cancel').show();
$codeInput.focus();
});
$('.coupon-code-cancel').on('click', (event) => {
event.preventDefault();
$couponContainer.hide();
$('.coupon-code-cancel').hide();
$('.coupon-code-add').show();
});
$couponForm.on('submit', (event) => {
const code = $codeInput.val();
event.preventDefault();
// Empty code
if (!code) {
return alert($codeInput.data('error'));
}
utils.api.cart.applyCode(code, (err, response) => {
if (response.data.status === 'success') {
this.refreshContent();
} else {
alert(response.data.errors.join('\n'));
}
});
});
}
Usage in Cornerstone
applyGiftCertificate
Apply a gift certificate to a cart.
utils.api.cart.applyGiftCertificate(code, callback)
Argument | Type | Description |
---|---|---|
code | string | Gift certificate code to apply |
callback | Function | Asynchronous function call to handle the results |
applyGiftCertificate Example
utils.api.cart.applyGiftCertificate(code, (err, resp) => {
if (resp.data.status === 'success') {
this.refreshContent();
} else {
swal({
text: resp.data.errors.join('\n'),
type: 'error',
});
}
});
});
}
Usage in Cornerstone
Countries Resource
These functions allow your theme or app to retrieve standardized country names, by numeric ID or by string.
getById
The getById
function retrieves standardized country names by numeric ID:
utils.api.countries.getById(countryId, callback)
Argument | Type | Description/Usage |
---|---|---|
countryId | Number | Country code |
callback | Function | Asynchronous function call to handle the results |
The following example a call to getById
, followed by a call to the getByName
function (described below):
/*
*Get country data by id wrapper
* @param {Number} id
* @param {Function} callback
*/
getById(id, callback) {
const url = this.endpoint + id;
this.remoteRequest(url, 'GET', {}, callback);
}
/*
* Get country data by country name
* @param name
* @param callback
*/
getByName(name, callback) {
const url = this.endpoint + name;
this.remoteRequest(url, 'GET', {}, callback);
}
}
getByName
The getByName
function retrieves states by country name, and returns an array of states that can be used in the callback:
utils.api.countries.getByName(countryName, callback)
Argument | Type | Description/Usage |
countryName | String | Country name |
callback | Function | Asynchronous function call to handle the results |
In the following example from common/state-country.js
, getByName
is called after the initial if test:
$('select[data-field-type="Country"]').on('change', (event) => {
const countryName = $(event.currentTarget).val();
if (countryName === '') {
return;
}
utils.api.country.getByName(countryName, (err, response) => {
if (err) {
alert(context.state_error);
return callback(err);
}
const $currentInput = $('[data-field-type="State"]');
if (!_.isEmpty(response.data.states)) {
// The element may have been replaced with a select, reselect it
const $selectElement = makeStateRequired($currentInput, context);
addOptions(response.data, $selectElement, options);
callback(null, $selectElement);
} else {
const newElement = makeStateOptional($currentInput, context);
callback(null, newElement);
}
});
});
Usage in Cornerstone
Product Attributes Resource
optionChange
The optionChange
function is fired when the customer selects a product option for the current cart item (for example, changing a shirt’s color from a default “yellow” to “green”).
utils.api.productAttributes.optionChange(productId, params, callback)
Argument | Type | Description/Usage |
---|---|---|
params | Object | Contains a collection of IDs that map to product properties (color, size, etc.) |
productId | Number | ID for this product |
callback | Function | Asynchronous function call to handle the results |
optionChange Examples
In this example (from common/product-details.js
), optionChange
is called to update options in a Quick View modal:
// Update product attributes. If we're in quick view and the product has options, then also update the initial view in case items are oos
if (_.isEmpty(productAttributesData) && hasOptions) {
const $productId = $('[name="product_id"]', $form).val();
utils.api.productAttributes.optionChange($productId, $form.serialize(), (err, response) => {
const attributesData = response.data || {};
this.updateProductAttributes(attributesData);
this.updateView(attributesData);
});
} else {
this.updateProductAttributes(productAttributesData);
}
Usage in Cornerstone
configureInCart
Configure product options in the cart.
utils.api.productAttributes.configureInCart(itemId, options, callback)
Argument | Type | Description |
---|---|---|
itemId | number | product ID |
params | object | |
callback | Function | Asynchronous function call to handle the results |
configureCart Example
utils.api.productAttributes.configureInCart(itemId, options, (err, response) => {
modal.updateContent(response.content);
this.bindGiftWrappingForm();
Usage in Cornerstone
Product Resource
The product.getById
function allows your code to retrieve, and to present, detailed product information by product ID.
getById
utils.api.product.getById(productId, params, callback)
Argument | Type | Description/Usage |
---|---|---|
productId | Number | ID for this product |
params | Object | Contains request options and/or presentation template |
callback | Function | Asynchronous function call to handle the results |
product.getById Example
$('body').on('click', '.quickview', (event) => {
event.preventDefault();
const productId = $(event.currentTarget).data('product-id');
modal.open({ size: 'large' });
utils.api.product.getById(productId, { template: 'products/quick-view' }, (err, response) => {
modal.updateContent(response);
modal.$content.find('.productView').addClass('productView--quickView');
return new ProductDetails(modal.$content.find('.quickView'), context);
});
});
Usage in Cornerstone
Search Resource
The search
function allows you to present a customized user interface for search results.
search
utils.api.search.search(query, params, callback)
Argument | Type | Description/Usage |
---|---|---|
query | String | Contains the customer’s search query |
params | Object | Contains request options and/or presentation template |
callback | Function | Asynchronous function call to handle the results |
search Example
const doSearch = _.debounce((searchQuery) => {
utils.api.search.search(searchQuery, { template: 'search/quick-results' }, (err, response) => {
if (err) {
return false;
}
$quickSearchResults.html(response);
});
}, 200);
Usage in Cornerstone
Config Object
A config
object can be passed in as part of the Stencil Utils API.
The object only returns data in the context of that call. The config will not be available to anything else. It will not surface objects that are not normally available to the page. Use YAML to return objects in the context of an entire page. Some config objects can only be used on the listed pages, while others are available globally.
getCartContent(cartItemHash, onComplete) {
const options = {
template: 'cart/preview',
params: {
suggest: cartItemHash,
},
config: {
cart: {
suggestions: {
limit: 4,
},
},
},
};
Search Attributes
{
"search": {
"product_results": {
"limit": 5
}
}
}
Brands
{
"brands": {
"limit": 5
}
}
{
"brand": {
"products": {
"limit": 5
}
}
}
Cart
{
"cart": {
"suggestions": {
"limit": 5
}
}
}
Product
{
"product": {
"videos": {
"limit": 11
},
"images": {
"limit": 12
},
"reviews": {
"limit": 13
},
"related_products": {
"limit": 14
},
"similar_by_views": {
"limit": 15
}
}
}
Blog
{
"blog": {
"posts": {
"limit": 5,
"pages": 3,
"summary": 10
}
}
}
Category
{
"category": {
"shop_by_price": false,
"products": {
"limit": 5
}
}
}
Global Objects
Products
{
"products": {
"featured": 3,
"new": 4,
"top_sellers": 10
}
}
{
"products": {
"featured": {
"limit": "5"
},
"new": {
"limit": "10"
},
"top_sellers": {
"limit": "15"
}
}
}
All Objects
{
"customer": {
"addresses": false,
"returns": true,
"wishlists": {
"limit": 3
},
"orders": {
"limit": 4
},
"recently_viewed_products": true
},
"products": {
"featured": {
"limit": 3
},
"new": {
"limit": 4
},
"top_sellers": {
"limit": 5
}
},
"carousel": true,
"blog": {
"recent_posts": {
"limit": 7
},
"summary": 6
},
"cart": true,
"shipping_messages": true,
"categories": {
"description": true
},
"shop_by_brand": {
"limit": 4
}
}
Resources
- Stencil Utils (BigCommerce GitHub)