in ,

Fix ‘Uncaught TypeError: Cannot read property ‘updateData’ of undefined’ in Magento 2

Fix Uncaught TypeError UpdateData

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));
}
},
view raw swatch-renderer.js hosted with ❤ by GitHub

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.

  1. Copy swatch-renderer.js to app/design/frontend/YourName/customtheme/Magento_Swatches/web/js/swatch-renderer.js
  2. Replace the updateBaseImage()-method with the following code:
    /**
    * 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));
    }
    },
  3. 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 besides en_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.

Buy me a beer?

Do you appreciate my work and support? Please consider supporting me by donating, so I can continue to develop and write useful solutions for you.

Choose amount

Personal Message

Thank you! 🙂

Written by Daan van den Bergh

Magento 2 Back-end Developer with a passion for trainlifting, airplane-gliding, hunting trees and creating fake hobbies.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.