cornerstone icon indicating copy to clipboard operation
cornerstone copied to clipboard

Custom JS not executing through a custom class on app.js

Open PSCPeter opened this issue 2 years ago • 3 comments

Expected behavior

Custom js file loads where the store-logo.html file is present.

Actual behavior

Custom js file does not execute where store-logo.html is present.

Steps to reproduce behavior

We added

const customClasses = {'components\common\store-logo': () => import('./custom/store-logo'),};

to app.js

and created a custom js file : to assets/js/custom

import PageManager from "../theme/page-manager";

export default class Custom extends PageManager {

onReady() {
    console.log("test");
}

}

We are not sure what we are missing to get this custom script to execute on the base theme's store-logo.html file. We have also tried this with header.html and had no luck.

PSCPeter avatar Aug 04 '22 14:08 PSCPeter

I'm facing a similar issue. I'm following the documentation, but I cannot get my custom js to fire on default bigcommerce html files through the customClasses area in app.js

dadameck avatar Aug 04 '22 17:08 dadameck

The original developer of that pattern, so perhaps I can help be of some assistance. Here is the original issue and PR. https://github.com/bigcommerce/cornerstone/issues/1339 https://github.com/bigcommerce/cornerstone/pull/1346

This pattern was meant to map custom JavaScript modules to custom templates for page types (categories, products, pages.) I did create another solution for use on our sites where we want to add to the functionality of default modules without modifying the default one (which makes cherry-picking commits a lot easier for us.) The default modules are ones provided by BigCommerce and mapped to page types.

Here is what our app.js looks like, minus our customClasses object map. You'll see that we create an object map below pageClasses called addonClasses where we map additional custom modules to a default page type. Further down, you'll see under the comment // Load addon imports that there's an import statement for loading these additional add-on modules for default page types.

Unfortunately, the template component components\common\store-logo can not be mapped to a JavaScript module as far as I'm aware. Sorry, I can't be of more help there, but hope this helps explain things further regarding mapping custom modules and default BigCommerce page types.

__webpack_public_path__ = window.__webpack_public_path__; // eslint-disable-line

import Global from './theme/_addons/global';

const getAccount = () => import('./theme/account');
const getLogin = () => import('./theme/auth');
const noop = null;

const pageClasses = {
    account_orderstatus: getAccount,
    account_order: getAccount,
    account_addressbook: getAccount,
    shippingaddressform: getAccount,
    account_new_return: getAccount,
    'add-wishlist': noop,
    account_recentitems: getAccount,
    account_downloaditem: getAccount,
    editaccount: getAccount,
    account_inbox: getAccount,
    account_saved_return: getAccount,
    account_returns: getAccount,
    account_paymentmethods: getAccount,
    account_addpaymentmethod: getAccount,
    account_editpaymentmethod: getAccount,
    login: getLogin,
    createaccount_thanks: getLogin,
    createaccount: getLogin,
    getnewpassword: getLogin,
    forgotpassword: getLogin,
    blog: noop,
    blog_post: noop,
    brand: () => import('./theme/brand'),
    brands: noop,
    cart: () => import('./theme/cart'),
    category: () => import('./theme/category'),
    compare: noop,
    page_contact_form: () => import('./theme/contact-us'),
    error: noop,
    404: noop,
    giftcertificates: noop,
    giftcertificates_balance: noop,
    giftcertificates_redeem: noop,
    default: noop,
    page: noop,
    product: noop,
    amp_product_options: noop,
    search: noop,
    rss: noop,
    sitemap: noop,
    newsletter_subscribe: noop,
    wishlist: noop,
    wishlists: noop,
};

const addonClasses = {
    404: () => import('./theme/_addons/404-error'),
    account_orderstatus: () => import('./theme/_addons/account'),
    blog: () => import('./theme/_addons/blog'),
    blog_post: () => import('./theme/_addons/blog'),
    brand: () => import('./theme/_addons/brand'),
    cart: () => import('./theme/_addons/cart'),
    login: () => import('./theme/_addons/auth'),
    category: () => import('./theme/_addons/category'),
    page_contact_form: () => import('./theme/_addons/contact-us'),
    default: () => import('./theme/_addons/home'),
    page: () => import('./theme/_addons/page'),
    product: () => import('./theme/_addons/product'),
};

const customClasses = { ... };

/**
 * This function gets added to the global window and then called
 * on page load with the current template loaded and JS Context passed in
 * @param pageType String
 * @param contextJSON
 * @returns {*}
 */
window.stencilBootstrap = function stencilBootstrap(pageType, contextJSON = null, loadGlobal = true) {
    const context = JSON.parse(contextJSON || '{}');

    return {
        load() {
            $(() => {
                // Load globals
                if (loadGlobal) {
                    Global.load(context);
                }

                const importPromises = [];

                // Find the appropriate page loader based on pageType
                const pageClassImporter = pageClasses[pageType];
                if (typeof pageClassImporter === 'function') {
                    importPromises.push(pageClassImporter());
                }

                // Load addon imports
                const addonClassImporter = addonClasses[pageType];
                if (typeof addonClassImporter === 'function') {
                    importPromises.push(addonClassImporter());
                }

                // See if there is a page class default for a custom template
                const customTemplateImporter = customClasses[context.template];
                if (typeof customTemplateImporter === 'function') {
                    importPromises.push(customTemplateImporter());
                }

                // Wait for imports to resolve, then call load() on them
                Promise.all(importPromises).then(imports => {
                    imports.forEach(imported => {
                        imported.default.load(context);
                    });
                });
            });
        },
    };
};

sacr3dc0w avatar Aug 05 '22 18:08 sacr3dc0w

@sacr3dc0w This is a helpful solution for not overriding the base cornerstone js files. And it will make upgrading the base cornerstone theme in my project easier in the future.

The code example also helped me realize that under pageClasses the "default" key is what maps to the home.html file. This is somewhat confusing and caused me some delays in trying to add javascript to our homepage. I was looking for a key named "home" and even tried adding home: () => import('./theme/home).

In any case, I think the addonClasses solution should be added to the documentation.

amfischer avatar Aug 04 '23 15:08 amfischer