Many people have complained on Magento Dev’s Github about a bug in Magento 2, which occurs when you try to pre-select configurable attributes by parsing the URL. It triggers an Uncaught TypeError
in your console and causes all Javascript execution to crash, causing the image gallery not be updated. In this tutorial I’ll show you how to squash this bug.
Pre-selecting Configurable Attributes
Magento 2 features a core-function, which allows you to pre-select configurable attributes by adding hash-parameters to the URL.
This function listens to the following pattern: # [attribute_id] = [attribute_value] & [attribute_id] = [attribute_value] &
etc.
This pattern is appended to the configurable products’ URL.
Parsing the URL to pre-select configurable attributes in Magento 2. An Example.
I have two configurable attributes (Memory and Color) for my product named ‘iPhone’. The ‘memory
‘ attribute has the attribute id 100
and the ‘color
‘ attribute’s id is 200
. The ‘Memory
‘ attribute has a few values available, one of which has the label ‘128 GB
‘ and the value ‘15
‘. For the ‘Color
‘ attribute we want to pre-select ‘Red
‘, which has the value ‘20
‘.
To pre-select these attributes using the integrated Magento 2 URL parser, we would use the following URL: http://mymagentostore.com/iphone#100=15&200=20
.
‘Uncaught TypeError: Cannot read property ‘updateData’ of undefined’ Explained
The bug in Magento 2’s core-code occurs when you use the previously mentioned feature. The image gallery should display the images attached to the pre-selected simple product. But the images are loaded using AJAX, and the above mentioned updateData-method is triggered before the images are finished loading:
/** | |
* Start update base image process based on event name | |
* @param {Array} images | |
* @param {jQuery} context | |
* @param {Boolean} isInProductView | |
* @param {String|undefined} eventName | |
*/ | |
updateBaseImage: function (images, context, isInProductView, eventName) { | |
var gallery = context.find(this.options.mediaGallerySelector).data('gallery'); | |
if (eventName === 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)); | |
} | |
}, |
The above method is located in vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js
.
It assumes the gallery object (self.options.mediaGallerySelector
) is fully-loaded and tries to save it in a variable (gallery
). After that the method processUpdateBaseImage()
is triggered, which tries to trigger the updateData()
-method on the undefined
variable gallery
.
This causes all JavaScript execution to crash and the image gallery to fallback to the images attached to the parent configurable product.
Fixing the Uncaught TypeError in Magento 2
Fixing the error is pretty easy. All we need to do is wait for the image gallery to be fully loaded, before executing the rest of the code. Magento 2 already offers an event for this, which is triggered when the image gallery is loaded: gallery:loaded
. It is also located in the else
-clause of the original code inside the updateBaseImage()
-method. But for some reason, there’s no check if gallery
is ever defined.
Modifying Magento 2 core-code is never advised. The best way to modify Magento 2’s core behaviour is using mixins. I’ve tried implementing this via a mixin, but I haven’t been able to make it work. The snippet below can probably be optimized further. At first sight, the whole if-else-statement seems unnecessary, but I haven’t tested it any further.
You can override the file using a module, but in this example I’m overriding the file using a theme override.
- Copy
swatch-renderer.js
toapp/design/frontend/YourName/customtheme/Magento_Swatches/web/js/swatch-renderer.js
- Replace the
updateBaseImage()
-method with the following code:This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters/** * Start update base image process based on event name * @param {Array} images * @param {jQuery} context * @param {Boolean} isInProductView * @param {String|undefined} eventName */ updateBaseImage: function (images, context, isInProductView, eventName) { var gallery = context.find(this.options.mediaGallerySelector).data('gallery'); // Check if gallery is defined. 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)); } }, - If you’re in developer-mode, all you have to do now is empty your static content:
rm -rf pub/static/*
. If you’re in production-mode it is advised to re-deploy static contentphp bin/magento setup:static-content:deploy en_US
. Make sure to define your locale-code (e.g.nl_NL
, if your webstore uses a different language/region besidesen_US
.
After you’ve applied the previous steps you’ve fixed a Magento 2-bug which prevents you from showing pre-selected configurable attributes with their corresponding image-gallery using Magento 2’s integrated URL parsing function. The JavaScript-error ‘Uncaught TypeError: Cannot read property 'updateData' of undefined
‘ will not be showing up in your Console anymore.
Hi Daan. Thanks for the tutorial. Although I’ve a small issue. The url hash doesn’t seem to work on my Magento 2. It redirects correctly and with all the parameters, but it doesn’t preselect the product attributes. Do you’ve any experience with this issue?
Hi Jimmy, I’m sorry for not responding earlier. I missed your comment.
Are you getting any errors in your console?
Hey Daan,
I am having the same issue as Jimmy. It redirects correctly to the parent but does not select the product attributes. Is this a recent issue with the new versions of Magento?
Thanks!
Jay