Stencil Utils Reference


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

  1. Run npm install @bigcommerce/stencil-utils to install the latest tagged version of stencil-utils for use with your theme.
  2. 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 [api.js]

getPage

Request a page using Ajax.
utils.api.getPage(url, options, callback)

Argument Type Description/Usage
url String URL to which you want to send a request (for example: localhost:4000/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

util.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/Usage
quantity int A sum of physical, digital, and custom product quantities and gift certificate quantities
callback Function Asynchronous function call to handle the results

getCartQuantity Example

utils.api.cart.getCartQuantity(quantity => {
		console.log(`Quantity: ${quantity}`);
});

Usage in Cornerstone


itemAdd

The itemAddfunction 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


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

Product Search Results

        {
           "search": {
              "product_results": {
                 "limit": 5
              }
           }
        }

Brands

Brand List Page

        {
           "brands": {
              "limit": 5
           }
        }

Brand Page

        {
           "brand": {
              "products": {
                 "limit": 5
              }
           }
        }

Cart

Cart Page

        {
           "cart": {
              "suggestions": {
                 "limit": 5
              }
           }
        }

Product

Product Page

        {
           "product": {
              "videos": {
                 "limit": 11
              },
              "images": {
                 "limit": 12
              },
              "reviews": {
                 "limit": 13
              },
              "related_products": {
                 "limit": 14
              },
              "similar_by_views": {
                 "limit": 15
              }
           }
        }

Blog

Blog Page

        {
           "blog": {
              "posts": {
                 "limit": 5,
                 "pages": 3,
                 "summary": 10
              }
           }
        }

Category

Category Page

        {
           "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