5

I'm trying to trigger custom event whenever Magento displays the product swatches in category view.

It looks like Magento uses ajax to load these swatches, they are not displayed on page load, they "pop" after a few moments. I need to add some custom JavaScript code after these swatches are actually displayed. So I thought the best way will be to trigger custom event just after Magento finishes to render the swatches. But I'm not sure how to do this correctly in Magento 2.

enter image description here

What I want to do is to trigger a custom event $(document).trigger('swatches-visible'); when a block of swatches is finally displayed on the page.

And then, an event handler will execute a function:

$(document).on('swatches-visible', function() { 
 doSomething(); 
});

That function doSomething() is already added via RequireJS in one of the template files:

<script type="text/javascript">
 requirejs(['jquery'], function(jQuery) {
 function doSomething()
 {
 // Here make some layout changes of the products list...
 }
 });
</script>
asked Oct 3, 2016 at 11:58
10
  • Are you loading your script via RequireJS? I ask this as you can tell Require to only load a script when a certain element has been rendered with x-magento-ini. See this section of the dev docs for more info - devdocs.magento.com/guides/v2.0/javascript-dev-guide/javascript/… Commented Oct 3, 2016 at 12:30
  • @Ben-Space48 I want to trigger custom event $(document).trigger('swatches-visible') when a block of swatches is finally displayed. And then, an event handler will execute a function: $(document).on('swatches-visible', function(e) { doSomething(); }); That function doSomething() is already added via RequireJS in one of the template files. What you proposed sounds like a good solution but I'm not sure how to use it in my case. Isn't Commented Oct 3, 2016 at 15:08
  • Isn't data-mage-init executed only on page load? Note that the blocks of swatches for all products, e.g. <div class="swatch-opt-1822">...</div>, are displayed with a delay, not instantly on page load. Commented Oct 3, 2016 at 15:20
  • I know data-mage-init is, x-magento-init is different although I'm not sure if that is also only on page load (the dev docs don't mention). If it is page load then the only other method I can think of is to initialise the JS inside the swatch template. Require works in templates to so I don't see why that wouldn't work. Commented Oct 3, 2016 at 15:33
  • Although JS inside a template isn't the cleanest method :( Commented Oct 3, 2016 at 15:34

3 Answers 3

12

I used the event 'swatch.initialized' to fire a function after swatches are loaded in the product page:

$(document).on('swatch.initialized', function() {
 // do something
})

The event is triggered in Magento_Swatches/js/swatch-renderer.js

$(this.element).trigger('swatch.initialized');
Piyush
5,9249 gold badges35 silver badges67 bronze badges
answered Jan 25, 2018 at 15:35
2

Try With This one.

 <script type="text/javascript">
 require(['jquery','Magento_Swatches/js/swatch-renderer'],function(,ドルswatch){
 $(document).on('swatch.initialized', function() {
 function doSomething()
 {
 // Here make some layout changes of the products list...
 }
 });
 </script> 
answered Jan 7, 2019 at 11:22
2

While @Guillem Lorman's answer is good. A more general approach, which gives you more control, is to use mixins. This allows you to trigger your script before/after a certain function has completed. Like this:

app/code/Namespace/ModuleName/view/frontend/requirejs-config.js

var config = {
 config: {
 mixins: {
 'Magento_Swatches/js/swatch-renderer': {
 'Namespace_ModuleName/js/swatch-renderer-mixin': true
 }
 }
 }
};

Then go through the code of swatch-renderer.js to see before/after which function you'd like to trigger your code. E.g. to plug into _RenderSwatchSelect you could do the following:

app/code/Namespace/ModuleName/viewfrontend/web/js/swatch-renderer-mixin.js

define([
 'jquery'
], function (
 $
) {
 'use strict';
 return function (widget) {
 $.widget('mage.SwatchRenderer', widget, {
 // Pay attention to parameters in the original function.
 _RenderSwatchSelect: function(config, chooseText) {
 // Trigger original function.
 this._super(config, chooseText);
 console.log('Yeah!');
 /**
 * If you want to trigger your function before the original function, 
 * you'd place this.super(config, chooseText) here.
 */
 },
 });
 return $.mage.SwatchRenderer;
 }
});
answered Dec 6, 2019 at 9:16
1
  • Exactly something that I was looking for. gives much more access than just initialise event. Thanks Commented Sep 25, 2020 at 11:28

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.