Magento2: Error with updating product image on configurable auto-select via URL parameters

Created on 26 Jan 2016  路  7Comments  路  Source: magento/magento2

When setting a configurable product's options via the URL, the gallery images do not update successfully intermittently. The following javascript error originating in updateBaseImage() within SwatchRenderer.js is thrown:

"Uncaught TypeError: Cannot read property 'updateData' of undefined"

From a quick glance, it's looking like the error is being caused due to the gallery not being fully initialized prior to updateBaseImage() trying to update the images.

It's usually not an issue when a user is clicking on the options since by that time the gallery has fully rendered (usually) and the gallery images are retrieved, but if the user is too quick at selecting or the configurable options are set almost immediately via URL parameters, then updateBaseImage fails.

Reproducing it is intermittent but later determined that if the images are retrieved quickly or are cached, then the gallery initializes quickly enough that by the time updateBaseImage executes, the gallery api is available. However, if there's even a slight delay in the gallery fully initializing (non cached images / server load / network traffic / slow connection), then updateBaseImage fails.

Catalog Cannot Reproduce Clear Description Format is not valid bug report

Most helpful comment

I found FIX/solution.
We need to have "column main" classes as parent of the gallery container.

All 7 comments

UP (m2.1)

Same issue here with magento 2.1

I found FIX/solution.
We need to have "column main" classes as parent of the gallery container.

zuzuman is right in that the gallery container must have a parent with the class of "column main" but you can change this.

In v2.1.5 on line 248 of the vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js file it reads:

gallery = $('[data-gallery-role=gallery-placeholder]', '.column.main'),

You can replace '.column.main' with your own selector so long as the element it selects in the DOM contains the gallery container.

I also tested this by removing the second arguement and passed a blank string ('') instead. This also worked so I'm not entirely sure what the point of the second arguement is in the line of code above. Maybe its there for performance purposes?

I think a better approach would be to use the gallery container class name as the selector rather than a generic class referring to the pages layout. Or an even better way could be to apply an ID to the gallery container and parse this in as the second arguement rather than using a class.

It would be nice to refactored this
https://github.com/magento/magento2/blob/develop/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js#L324-L327
https://github.com/magento/magento2/blob/develop/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js#L652-L654
https://github.com/magento/magento2/blob/develop/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js#L1019-L1026
https://github.com/magento/magento2/blob/develop/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js#L1039-L1045
https://github.com/magento/magento2/blob/develop/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js#L1057

I would just add a product-item-info selector to the column main selectors on product view page
screenshot from 2017-09-12 15-09-37

I must to add a ugly patch for my ajax popup. it work now in the category view page.
~~~diff
-


+

diff --git a/view/frontend/web/css/ajax.less b/view/frontend/web/css/ajax.less
.ajax-modal-popup {

  • .column.main {
  • width: 100% !important;
  • }
    +
    ~~~

@tigerx7, thank you for your report.
We were not able to reproduce this issue by following the steps you provided. If you'd like to update it, please reopen the issue.
We tested the issue on 2.3.0-dev, 2.1.10, 2.2.1

@tigerx,

The fix to this is pretty simple actually:

Just update the updateBaseImage()-method with the following:

updateBaseImage: function (images, context, isInProductView, eventName) {
    var gallery = context.find(this.options.mediaGallerySelector).data('gallery');

    if (eventName === undefined && gallery !== undefined) {
        this.processUpdateBaseImage(images, context, isInProductView, gallery);
    } else {
        context.find(this.options.mediaGallerySelector).on('gallery:loaded', function (loadedGallery) {
            loadedGallery = context.find(this.options.mediaGallerySelector).data('gallery');
            this.processUpdateBaseImage(images, context, isInProductView, loadedGallery);
        }.bind(this));
    }
},

All you need to do is add a check if gallery is actually defined. If it isn't, it'll wait for the gallery to be loaded.

Was this page helpful?
0 / 5 - 0 ratings