Skip to content
intermediate Phase 56 · Frontend Styling

JavaScript Mixins

Understanding JavaScript mixins in Magento 2: mixin configuration, extending JS components, and the plugin system for JavaScript

45m
0 problems
Topic Progress 0%

Mixin Basics

What is a JavaScript Mixin?

A mixin is a function that takes a target component and returns an extended version of it.

Creating a Mixin

// view/frontend/web/js/component-mixin.js
define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            // Override existing method
            initialize: function() {
                this._super();
                console.log('Mixin applied');
                return this;
            },
            
            // Add new method
            getCustomData: function() {
                return 'custom data';
            }
        });
    };
});

Mixin Structure

define([], function() {
    'use strict';
    
    // Must return a function
    return function(target) {
        // target is the original component
        
        // Return extended component
        return target.extend({
            // New or overridden methods
        });
    };
});

Key Points

  • Mixin must return a function
  • Function receives target component
  • Returns target.extend() with changes
  • No direct modification of original

Registering Mixins

requirejs-config.js Registration

// view/frontend/requirejs-config.js
var config = {
    config: {
        'mixins': {
            'Vendor_Module/js/original-component': {
                'Vendor_Module/js/component-mixin': true
            }
        }
    }
};

Multiple Mixins

var config = {
    config: {
        'mixins': {
            'Vendor_Module/js/component': {
                'Vendor_Module/js/mixin-1': true,
                'Vendor_Module/js/mixin-2': true,
                'ThirdParty_Module/js/mixin': true
            }
        }
    }
};

Conditional Mixins

var config = {
    config: {
        'mixins': {
            'Vendor_Module/js/component': {
                'Vendor_Module/js/mixin': {
                    'enabled': true
                }
            }
        }
    }
};

Module-Specific Mixins

var config = {
    config: {
        'mixins': {
            'Magento_Catalog/js/product/list': {
                'Vendor_Module/js/catalog-mixin': true
            },
            'Magento_Checkout/js/view/cart': {
                'Vendor_Module/js/cart-mixin': true
            }
        }
    }
};

Extending Components

Override Methods

define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            // Override existing method
            getPrice: function() {
                var price = this._super();
                return price * 1.1; // Add 10% tax
            }
        });
    };
});

Add Methods

define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            // New method
            formatPrice: function(price) {
                return '$' + price.toFixed(2);
            },
            
            // Override to use new method
            getPrice: function() {
                var price = this._super();
                return this.formatPrice(price);
            }
        });
    };
});

Modify Properties

define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            defaults: {
                template: 'Vendor_Module/custom-template',
                customProperty: 'value'
            },
            
            initialize: function() {
                this._super();
                this.customProperty = 'new value';
                return this;
            }
        });
    };
});

Add Event Listeners

define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            initialize: function() {
                this._super();
                
                // Add event listener
                this.on('datachanged', function(data) {
                    console.log('Data changed:', data);
                });
                
                return this;
            }
        });
    };
});

Mixin Best Practices

Always Call _super()

// CORRECT
initialize: function() {
    this._super();
    // Your code
    return this;
}

// WRONG - breaks parent functionality
initialize: function() {
    // Your code without _super()
}

Return this

initialize: function() {
    this._super();
    // Your code
    return this; // Important for chaining
}

Keep Mixins Focused

// GOOD - Single responsibility
define([], function() {
    return function(target) {
        return target.extend({
            formatPrice: function(price) {
                return '$' + price.toFixed(2);
            }
        });
    };
});

// BAD - Too many changes
define([], function() {
    return function(target) {
        return target.extend({
            method1: function() {},
            method2: function() {},
            method3: function() {},
            // ... too many changes
        });
    };
});

Use Meaningful Names

// GOOD
'Vendor_Module/js/price-formatter-mixin'

// BAD
'Vendor_Module/js/mixin1'

Document Your Mixin

/**
 * Price formatter mixin for Magento_Catalog/js/product/list
 * Adds custom price formatting
 */
define([], function() {
    'use strict';
    
    return function(target) {
        return target.extend({
            formatPrice: function(price) {
                return '$' + price.toFixed(2);
            }
        });
    };
});

Quiz

1. What must a mixin function return?

Question 1 options

2. Where are mixins registered?

Question 2 options

3. Why should you call _super() in mixins?

Question 3 options

Flashcards

Question

What is a JavaScript mixin?

Answer

A function that extends a component without modifying the original

Question

Where are mixins registered?

Answer

In requirejs-config.js under config.mixins

Question

Why call _super()?

Answer

To maintain parent functionality

Question

What should a mixin return?

Answer

target.extend() with the extended component

Question

How do you add a new method in a mixin?

Answer

Add the method to the target.extend() object

Revision Notes

Key Takeaways

  • 1. Mixins extend components without modifying originals
  • 2. Register mixins in requirejs-config.js
  • 3. Always call _super() to maintain parent functionality
  • 4. Keep mixins focused on single responsibility
  • 5. Return this for proper chaining

Interview Tips

  • Explain the mixin pattern and its benefits
  • Know how to register and create mixins
  • Discuss when to use mixins vs inheritance
  • Be ready to debug mixin issues

Cheat Sheet

Mixin structure:
define([], function() {
    return function(target) {
        return target.extend({
            method: function() {
                this._super(); // Call parent
                // Custom code
                return this;
            }
        });
    };
});

Registration:
config: {
    'mixins': {
        'target/module': {
            'mixin/module': true
        }
    }
}