How to Override Specific Method in price-utils.js

magento2mixinsunderscorejs

Currently I successfully override the Price display base on local currency on other pages. But I got a problem on Product Details page. The price is override by price-utils.js file:

Magento/Catalog/view/base/web/js/price-utils.js

on formatPrice() method on line number 73.

(precision ? decimalSymbol + am.toFixed(2).replace(/-/, 0).slice(2) : '');

I tried to override the method via mixins.

requirejs-config.js

var config = {
    'config': {
        'mixins': {
            'Magento_Catalog/js/price-utils': {
                'MyModule_PriceDecimal/js/price-utils-mixin': true
            }
        }
    }
};

price-utils-mixin.js

define([
    'jquery',
    'underscore'
], function ($, _) {
    'use strict';

    var globalPriceFormat = {
        requiredPrecision: 2,
        integerRequired: 1,
        decimalSymbol: ',',
        groupSymbol: ',',
        groupLength: ','
    };

    return {
        formatPrice: formatPrice
    };

    /**
     * Formatter for price amount
     * @param  {Number}  amount
     * @param  {Object}  format
     * @param  {Boolean} isShowSign
     * @return {String}              Formatted value
     */
    function formatPrice(amount, format, isShowSign) {
        format = _.extend(globalPriceFormat, format);

        // copied from price-option.js | Could be refactored with varien/js.js

        var precision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision,
            integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired,
            decimalSymbol = format.decimalSymbol === undefined ? ',' : format.decimalSymbol,
            groupSymbol = format.groupSymbol === undefined ? '.' : format.groupSymbol,
            groupLength = format.groupLength === undefined ? 3 : format.groupLength,
            pattern = format.pattern || '%s',
            s = '',
            i, pad,
            j, re, r, am;

        if (isShowSign === undefined || isShowSign === true) {
            s = amount < 0 ? '-' : (isShowSign ? '+' : '');
        } else if (isShowSign === false) {
            s = '';
        }
        pattern = pattern.indexOf('{sign}') < 0 ? s + pattern : pattern.replace('{sign}', s);

        // we're avoiding the usage of to fixed, and using round instead with the e representation to address
        // numbers like 1.005 = 1.01. Using ToFixed to only provide trailig zeroes in case we have a whole number
        i = parseInt(amount = Number(Math.round(Math.abs(+amount || 0) + 'e+' + precision) + ('e-' + precision)) , 10) + '';
        pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0;

        i = stringPad('0', pad) + i;

        j = i.length > groupLength ? i.length % groupLength : 0;
        re = new RegExp('(\\d{' + groupLength + '})(?=\\d)', 'g');

        // replace(/-/, 0) is only for fixing Safari bug which appears
        // when Math.abs(0).toFixed() executed on '0' number.
        // Result is '0.-0' :(

        am = Number(Math.round(Math.abs(amount - i) + 'e+' + precision) + ('e-' + precision));
        r = (j ? i.substr(0, j) + groupSymbol : '') +
            i.substr(j).replace(re, '$1' + groupSymbol) +
            (precision ? decimalSymbol + am.toFixed(precision).replace(/-/, 0).slice(2) : '');

        return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    }
});

You will noticed that I have change from

(precision ? decimalSymbol + am.toFixed(2).replace(/-/, 0).slice(2) : '');

To

(precision ? decimalSymbol + am.toFixed(precision).replace(/-/, 0).slice(2) : '');

The script is working but I have a console error:

fd70f83ecce9b7063bc426e38ccbea7f.js:2154 Uncaught TypeError: mixin is not a function
    at fd70f83ecce9b7063bc426e38ccbea7f.js:2154
    at Array.forEach (<anonymous>)
    at applyMixins (fd70f83ecce9b7063bc426e38ccbea7f.js:2153)
    at fd70f83ecce9b7063bc426e38ccbea7f.js:2173
    at Object.execCb (fd70f83ecce9b7063bc426e38ccbea7f.js:1650)
    at Module.check (fd70f83ecce9b7063bc426e38ccbea7f.js:866)
    at Module.<anonymous> (fd70f83ecce9b7063bc426e38ccbea7f.js:1113)
    at fd70f83ecce9b7063bc426e38ccbea7f.js:132
    at fd70f83ecce9b7063bc426e38ccbea7f.js:1156
    at each (fd70f83ecce9b7063bc426e38ccbea7f.js:57)

That's the problem I have currently, I wanted to know how/what would be the best way to override this method without having any error on mixins js console toolbar.

Any suggestions/help is always appreciated.
Thanks!

Best Answer

Using mixins is to follow the best practice. But in your script, should try:

define([
    'jquery',
    'underscore'
   ],
    function ($, _) {
        'use strict';
        return function (target) {

            target.formatPrice = function formatPrice(amount, format, isShowSign) {
                //Your custom format price here
            };

            return target;
    };
});

[EDIT] Add others dependencies if we want.

Related Topic