TABLE OF CONTENTS
- Why should the button be initialized?
- What are Custom Events in Javascript?
- How we can initialize the EPI button on collections?
- Step 1: Determine where we need to initialise the button (infinite load, collections, quickview)
- Step 2: Check for network calls that get triggered when filters are applied
- Step 3: Dispatch the custom event
- Step 4: Listen to our custom event by creating a custom file
- Step 5: Include the swym-custom file inside the theme.liquid
- Step 6: Implementing a setTimeout
The EPI button code on the collections exists on the product cards in the collections but they simply don’t show up when filters are applied / dynamic sections.
Ever wondered why? - That’s because the EPI button was not initialized!
Why should the button be initialized?
The button needs to be initialized to ensure it is loaded and ready for use before clicking. In dynamically rendered sections such as filters, an infinite scroll that re-renders collection tiles, and Quickview modals, the buttons needs to be initialized before they can be used.
The initialization process ensures that the necessary attributes are loaded and available for the button to function correctly. The button may not work correctly without proper initialization, leading to errors or unexpected behavior.
Note: Button initialization is only required on the dynamic sections of the collections page. For instance, if the entire page reloads after applying filters, the buttons are automatically initialized during the load as the product cards' markup are built.
What are Custom Events in Javascript?
(This section is only meant for the logic explanation and can be skipped)
In JavaScript, custom events allow developers to create and dispatch their own events, which can be detected and handled by other parts of the application. Custom events enable the decoupling of various components of an application, making the code more modular, reusable, and easier to maintain.
To create a custom event, you need to use the CustomEvent constructor, which takes two arguments - the event name and an optional object that specifies additional properties for the event. Once the custom event is created, you can dispatch it using the dispatchEvent method, passing in the custom event object as an argument.
Here's an example of how to create and use a custom event in JavaScript:
// Create a custom event const customEvent = new CustomEvent('customEvent', { detail: { message: 'Hello from the custom event!' } }); // Dispatch the custom event on a button click const button = document.querySelector('button'); button.addEventListener('click', function() { button.dispatchEvent(customEvent); }); // Handle the custom event const output = document.querySelector('.output'); document.addEventListener('customEvent', function(event) { output.textContent = event.detail.message; });
In this example, we create a custom event called 'customEvent' with a message payload of 'Hello from the custom event!'. We then dispatch the event when the user clicks on a button.
Finally, we handle the custom event by listening to it on the document object and updating the content of a DOM element with the message payload.
When the user clicks on the button, the custom event is dispatched, and the event listener is triggered, updating the content of the output element with the custom message.
How we can initialize the EPI button on collections?
Pre-requisite: The EPI button can only be initialised when all the attributes such as data-variant-id, data-product-url & data-product-id are present and valid as present in our collections article.
Step 1: Determine where we need to initialise the button (infinite load, collections, quickview)
In this example, we’d have to initialize the button on the filters
The button code is actually present here, but it is not initialized to be shown on the store-front
How to differentiate between an initialised button and un-initialised button? swym-loaded class helps us to differentiate between initialised button and un-initialised button. To elaborate, an un-initialised button wouldn’t have the above swym-loaded class in its ClassList!
Step 2: Check for network calls that get triggered when filters are applied
Open the developers tool (⌘⌥I) > Network > Apply Fetch/XHR filter > Now apply filters on the collections to record the network calls > Choose a network call > Open the Initiator tab and go through the call stack
While going through the callstack, ignore any swym network calls and other uglified files!
For this store, whenever filters are being applied the products are dynamically re-loaded using the renderSectionFromFetch function in the facets.js file. Thus, we have to dispatch a custom event to initialize our buttons!
Here’s the code to dispatch our custom event:
document.dispatchEvent(new CustomEvent("swym:collections-loaded"));
Note: The custom event doesn’t have to be “swym:collections-loaded”. It can be named anything but make sure to listen to the same!
If you are not sure if a particular functions gets triggered when filters are applied, just add console logs and analyse the console when filters are applied
Step 3: Dispatch the custom event
It is advised to dispatch the custom event at the end of the function so that the theme functionality is not hindered, like this:
static renderSectionFromFetch(url, event) { fetch(url) .then(response => response.text()) .then((responseText) => { const html = responseText; FacetFiltersForm.filterData = [...FacetFiltersForm.filterData, { html, url }]; FacetFiltersForm.renderFilters(html, event); FacetFiltersForm.renderProductGridContainer(html); FacetFiltersForm.renderProductCount(html); }); // Swym code starts here document.dispatchEvent(new CustomEvent("swym:collections-loaded")); // Swym code ends here }
Step 4: Listen to our custom event by creating a custom file
Create a swym-custom.liquid file inside the Snippets sections and the following code snippet
<script defer> function swymCallbackFn(swat){ document.addEventListener("swym:collections-loaded", function(){ swat.initializeActionButtons("<<Collections Grid PARENT Selector>>"); }); } if(!window.SwymCallbacks){ window.SwymCallbacks = []; } window.SwymCallbacks.push(swymCallbackFn); </script>
When a script tag includes the defer attribute, it tells the browser to defer the execution of the script until the HTML content has been fully loaded and parsed.
Step 5: Include the swym-custom file inside the theme.liquid
Please use the below code snippet to include the swym-custom file in theme.liquid
{% include 'swym-custom' %}
So now the EPI button should work on filters, right?
There might be some cases where our custom event was triggered even before the dynamic sections have loaded. In these cases, we need to delay the execution of our custom event. We can achieve this using setTimeout function in Javascript
What is setTimeout?
setTimeout is a built-in JavaScript function that allows you to schedule the execution of a specified piece of code after a certain delay. It takes two arguments: a function to execute, and a delay time in milliseconds.
The general syntax for using setTimeout is as follows:
setTimeout(function, delay);
Step 6: Implementing a setTimeout
As mentioned in the above section, we would have to declare a function expression with our custom event in its body! For this example, it would look as follows:
<script defer> function swymCallbackFn(swat){ document.addEventListener("swym:collections-loaded", function(){ setTimeout( () => { swat.initializeActionButtons("body"); },1500); }) } if(!window.SwymCallbacks){ window.SwymCallbacks = []; } window.SwymCallbacks.push(swymCallbackFn); </script>
Ta-da! Now the EPI button would work as expected even on the filters!
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article