{"_id":"584b3fa3b1578425007a4c48","parentDoc":null,"category":{"_id":"584b3de7e5f3a42300df6ef7","project":"55a6e72e8cc73e0d00096635","__v":0,"version":"55a6e72f8cc73e0d00096638","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-12-09T23:27:35.491Z","from_sync":false,"order":16,"slug":"javascript-api","title":"JavaScript Customization"},"user":"55a6caa022cfa321008e01d6","project":"55a6e72e8cc73e0d00096635","version":{"_id":"55a6e72f8cc73e0d00096638","project":"55a6e72e8cc73e0d00096635","hasReference":false,"__v":29,"hasDoc":true,"createdAt":"2015-07-15T23:05:19.125Z","releaseDate":"2015-07-15T23:05:19.125Z","categories":["55a6e7308cc73e0d00096639","55b7ed07aea7c8190058badb","5604567c0c78b00d0039b191","5605e6f23a93940d002b3e4a","5605f2bba4574a0d00811365","5605f309a4574a0d00811366","5608e3b98aedf50d0004cf8f","5608e4318aedf50d0004cf90","5608e6b5a7cc2f0d00d9754d","5608e6d331beb60d001b6560","5608f879a7cc2f0d00d97580","560b097887b71d0d000d3bd9","560b13cbafa0990d00979545","560b5cbec341310d00de2a01","560b5cd0c341310d00de2a02","566a35b81e08750d00a0c49b","566a3e8503b4b20d00d02a4a","567889d307bf6a0d0083edc8","569c8b7c15bb390d00db6f9d","56b254dc65ddf50d0076ba8f","57a8ebc4cdeea20e001d2a63","57e48a4000c8680e00fae6e7","5808216773557d0f00a1e428","58105ad54a8aa50f00aa4cba","58105bf298aea40f00afa3ba","58105f548a4aed0f00d67536","581061b898aea40f00afa3be","584b3de7e5f3a42300df6ef7","596839a75965d400155bb750"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-12-09T23:34:59.788Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":6,"body":"[block:html]\n{\n  \"html\": \"<!--\\n1) √ Change title.\\n2) √ Change intro.\\n3) √ Change class name from \\\"Auth\\\" to \\\"Blog\\\".\\n4) √ Reposition between \\\"Adding JS to Your Theme\\\" and \\\"Basic Non-npm Example\\\".\\n5) √ Change all links on splash page.\\n\\n√ [Removed, pertained to aborted npm intermediate example:]\\nIn this example, we will use the React and React Material-UI \\\"chip\\\" component to display an \\\"On Sale\\\" badge on product pages. -->\"\n}\n[/block]\nThis page provides an overview of the pages where you can customize JavaScript, the relevant callback methods, and two Handlebars helpers available for JavaScript injection. It includes:\n\n* [stencil-utils Library](#library) \n* [JavaScript API](#api)\n* [Callback Methods](#callback)\n* [JavaScript Template Context Injection](#inject)\n\n## <span id=\"library\"> stencil-utils Library </span>\n[stencil-utils](https://github.com/bigcommerce/stencil-utils) is our supporting library for events and remote interactions.\n\n## <span id=\"api\"> JavaScript API </span>\nStencil themes include an API for running JavaScript on a per-page basis. To properly write JavaScript for your theme, you will have the following page types available to you:\n\n* \"pages/account/addresses\"\n* \"pages/account/add-address\"\n* \"pages/account/add-return\"\n* \"pages/account/add-wishlist\"\n* \"pages/account/recent-items\"\n* \"pages/account/download-item\"\n* \"pages/account/edit\"\n* \"pages/account/return-saved\"\n* \"pages/account/returns\"\n* \"pages/auth/login\"\n* \"pages/auth/account-created\"\n* \"pages/auth/create-account\"\n* \"pages/auth/new-password\"\n* \"pages/blog\"\n* \"pages/blog-post\"\n* \"pages/brand\"\n* \"pages/brands\"\n* \"pages/cart\"\n* \"pages/category\"\n* \"pages/compare\"\n* \"pages/errors\"\n* \"pages/gift-certificate/purchase\"\n* \"pages/gift-certificate/balance\"\n* \"pages/gift-certificate/redeem\"\n* \"global\"\n* \"pages/home\"\n* \"pages/order-complete\"\n* \"pages/page\"\n* \"pages/product\"\n* \"pages/search\"\n* \"pages/sitemap\"\n* \"pages/subscribed\"\n* \"page/account/wishlist-details\"\n* \"pages/account/wishlists\"\n\nThese page types correspond to the pages within your theme. Each of these page types maps to an ES6 module that extends the base `PageManager` abstract class:\n\n```javascript\n    export default class Blog extends PageManager {\n        constructor() {\n            //Setup code goes here – attach to internals, and use internals as you would 'this'\n        }\n    }\n```\n\n## <span id=\"callback\"> Callback Methods </span>\n\nWithin `PageManager`, you will see methods that are available from all your classes. But three methods are especially important. The following methods have the signature `func (callback)`, with the callback taking `callback(err)` in case of an error.\n\n### before(callback)\n\nWhen this method is implemented in your class, the code contained will be executed after the constructor but before the `loaded()` method. This will provide a shim for your code before your main implementation logic could run.\n\n```javascript\n    export default class Blog extends PageManager {\n        constructor() {\n            //Setup code goes here\n        }\n        before(callback) {\n            //Code that should be ran before any other code in this class\n\n            //Callback must be called to move on to the next method\n            callback();\n        }\n    }\n```\n\n### loaded(callback)\nThis method will be called when the constructor has ran and `before()` has executed. Main implementation code should live in the `loaded()` method.\n\n```javascript\n    export default class Blog extends PageManager {\n        constructor() {\n            //Setup code goes here\n        }\n        loaded(callback) {\n            //Main implementation logic here\n\n            //Callback must be called to move on to the next method\n            callback();\n        }\n    }\n```\n\n### after(callback)\n\nThis method is for any cleanup that may need to happen, and it will be executed after `before()` and `loaded()`.\n\n```javascript\n    export default class Blog extends PageManager {\n        constructor() {\n            //Set up code goes here\n        }\n        after(callback) {\n            //Main implementation logic here\n\n            //Callback must be called to move on to the next method\n            callback();\n        }\n    }\n```\n\n## <span id=\"inject\"> JavaScript Template Context Injection </span>\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"The following topic is covered in greater detail under [Other Handlebars Helpers](https://stencil.bigcommerce.com/docs/other-handlebars-helpers#inject).\",\n  \"title\": \"For More Information\"\n}\n[/block]\nOccasionally, you might need to use dynamic data from the template context within your theme's client-side application code. Two helpers are provided to help achieve this.\n\nThe `inject` helper allows you to compose a json object with a subset of the template context to be sent to the browser:\n\n```\n{{inject \"stringBasedKey\" contextValue}}\n```\n\nTo retrieve the parsable JSON object, just call `{{jsContext}}` after all of the `{{inject}}` calls.\n\nFor example, to set up the product name in your client-side app, you can do this if you're in the context of a product:\n\n```html\n{{inject \"myProductName\" product.title}}\n\n<script>\n// Note the lack of quotes around the jsContext handlebars helper, it becomes a string automatically.\nvar jsContext = JSON.parse({{jsContext}}); //jsContext would output \"{\\\"myProductName\\\": \\\"Sample Product\\\"}\" which can feed directly into your JavaScript\n\nconsole.log(jsContext.myProductName); // Will output: Sample Product\n</script>\n```\n\nYou can compose your JSON object across multiple pages, to create a different set of client-side data depending on the currently loaded template context.\n\nStencil's Cornerstone base theme makes the `jsContext` available as `this.context`, both on the active page scoped and on global `PageManager` objects.","excerpt":"Custom JavaScript","slug":"js-pg-cycle","type":"basic","title":"Page Types and Life Cycle"}

Page Types and Life Cycle

Custom JavaScript

[block:html] { "html": "<!--\n1) √ Change title.\n2) √ Change intro.\n3) √ Change class name from \"Auth\" to \"Blog\".\n4) √ Reposition between \"Adding JS to Your Theme\" and \"Basic Non-npm Example\".\n5) √ Change all links on splash page.\n\n√ [Removed, pertained to aborted npm intermediate example:]\nIn this example, we will use the React and React Material-UI \"chip\" component to display an \"On Sale\" badge on product pages. -->" } [/block] This page provides an overview of the pages where you can customize JavaScript, the relevant callback methods, and two Handlebars helpers available for JavaScript injection. It includes: * [stencil-utils Library](#library) * [JavaScript API](#api) * [Callback Methods](#callback) * [JavaScript Template Context Injection](#inject) ## <span id="library"> stencil-utils Library </span> [stencil-utils](https://github.com/bigcommerce/stencil-utils) is our supporting library for events and remote interactions. ## <span id="api"> JavaScript API </span> Stencil themes include an API for running JavaScript on a per-page basis. To properly write JavaScript for your theme, you will have the following page types available to you: * "pages/account/addresses" * "pages/account/add-address" * "pages/account/add-return" * "pages/account/add-wishlist" * "pages/account/recent-items" * "pages/account/download-item" * "pages/account/edit" * "pages/account/return-saved" * "pages/account/returns" * "pages/auth/login" * "pages/auth/account-created" * "pages/auth/create-account" * "pages/auth/new-password" * "pages/blog" * "pages/blog-post" * "pages/brand" * "pages/brands" * "pages/cart" * "pages/category" * "pages/compare" * "pages/errors" * "pages/gift-certificate/purchase" * "pages/gift-certificate/balance" * "pages/gift-certificate/redeem" * "global" * "pages/home" * "pages/order-complete" * "pages/page" * "pages/product" * "pages/search" * "pages/sitemap" * "pages/subscribed" * "page/account/wishlist-details" * "pages/account/wishlists" These page types correspond to the pages within your theme. Each of these page types maps to an ES6 module that extends the base `PageManager` abstract class: ```javascript export default class Blog extends PageManager { constructor() { //Setup code goes here – attach to internals, and use internals as you would 'this' } } ``` ## <span id="callback"> Callback Methods </span> Within `PageManager`, you will see methods that are available from all your classes. But three methods are especially important. The following methods have the signature `func (callback)`, with the callback taking `callback(err)` in case of an error. ### before(callback) When this method is implemented in your class, the code contained will be executed after the constructor but before the `loaded()` method. This will provide a shim for your code before your main implementation logic could run. ```javascript export default class Blog extends PageManager { constructor() { //Setup code goes here } before(callback) { //Code that should be ran before any other code in this class //Callback must be called to move on to the next method callback(); } } ``` ### loaded(callback) This method will be called when the constructor has ran and `before()` has executed. Main implementation code should live in the `loaded()` method. ```javascript export default class Blog extends PageManager { constructor() { //Setup code goes here } loaded(callback) { //Main implementation logic here //Callback must be called to move on to the next method callback(); } } ``` ### after(callback) This method is for any cleanup that may need to happen, and it will be executed after `before()` and `loaded()`. ```javascript export default class Blog extends PageManager { constructor() { //Set up code goes here } after(callback) { //Main implementation logic here //Callback must be called to move on to the next method callback(); } } ``` ## <span id="inject"> JavaScript Template Context Injection </span> [block:callout] { "type": "info", "body": "The following topic is covered in greater detail under [Other Handlebars Helpers](https://stencil.bigcommerce.com/docs/other-handlebars-helpers#inject).", "title": "For More Information" } [/block] Occasionally, you might need to use dynamic data from the template context within your theme's client-side application code. Two helpers are provided to help achieve this. The `inject` helper allows you to compose a json object with a subset of the template context to be sent to the browser: ``` {{inject "stringBasedKey" contextValue}} ``` To retrieve the parsable JSON object, just call `{{jsContext}}` after all of the `{{inject}}` calls. For example, to set up the product name in your client-side app, you can do this if you're in the context of a product: ```html {{inject "myProductName" product.title}} <script> // Note the lack of quotes around the jsContext handlebars helper, it becomes a string automatically. var jsContext = JSON.parse({{jsContext}}); //jsContext would output "{\"myProductName\": \"Sample Product\"}" which can feed directly into your JavaScript console.log(jsContext.myProductName); // Will output: Sample Product </script> ``` You can compose your JSON object across multiple pages, to create a different set of client-side data depending on the currently loaded template context. Stencil's Cornerstone base theme makes the `jsContext` available as `this.context`, both on the active page scoped and on global `PageManager` objects.