我们如何定制内置的Angular"货币"过滤?

时间:2015-03-16 06:00:14

标签: javascript angularjs filter currency

我使用Angular"货币"过滤以显示购物车中的价格。价格从后端服务器获取。因此,有时可能无法向用户显示价格。在这种情况下,我只想向用户显示价格与货币字段在同一字段中不可用。我无法在货币过滤器中显示纯文本。我找到的唯一解决方案是在价格不可用时保持另一个文本字段显示/隐藏。但这是我认为不必要的。有没有办法扩展或覆盖内置的"货币" Angular js过滤器?请欣赏一些帮助。

 <div class="large-12 medium-12 small-12 columns pad-none nzs-pro-list-item-price">
    {{item.ItmPrice|currency}}
</div>

3 个答案:

答案 0 :(得分:1)

创建自定义过滤器,当值存在时,内部将使用货币,否则它将返回您要显示的text

<强>标记

{{amount | customFormat:"USD$": "N/A"}}

过滤

.filter('customFormat', function($filter) {
  return function(value, format, text) {
    if (angular.isDefined(value) && value != null)
      return $filter('currency')(value, format);
    else
      return text;
  }
});

Working Plunkr

答案 1 :(得分:0)

我认为最好的方法是重写货币过滤器,以便您可以对模式,分组分隔符,小数分隔符和&amp;符号位置

    <span>
      {{26666662.5226 | fmtCurrency :"##.###,###" : "." : "," : "$" : "first"}}
    </span>

重新开始: $ 26.666.662,523

过滤

app.filter("fmtCurrency", ['CurrencyService', function sasCurrency(CurrencyService) {
        return function (amount, pattern, groupingSeparator, decimalSeparator, currencySymbol, symbolPosition) {

            var patternInfo = CurrencyService.parsePattern(pattern, groupingSeparator, decimalSeparator);
            var formattedCurrency = CurrencyService.formatCurrency(amount, patternInfo, groupingSeparator, decimalSeparator);

            if (symbolPosition === 'last')
                return formattedCurrency + currencySymbol;
            else
                return currencySymbol + formattedCurrency;
        };
    }])

服务:formatNumber与角度货币过滤器中使用的功能相同,此处正在服务中使用

app.service("CurrencyService", function () {

        var PATTERN_SEP = ';',
            DECIMAL_SEP = '.',
            GROUP_SEP = ',',
            ZERO = '0',
            DIGIT = "#";

        var MAX_DIGITS = 22;
        var ZERO_CHAR = '0';

        return {
            parsePattern: function (pattern, groupingSeparator, decimalSeparator) {
                return parsePattern(pattern, groupingSeparator, decimalSeparator);
            },
            formatCurrency: function (amount, patternInfo, groupingSeparator, decimalSeparator) {
                return formatNumber(amount, patternInfo, groupingSeparator, decimalSeparator);
            }
        }


        /*
         * Currency formatter utility
         */

        function isUndefined(value) { return typeof value === 'undefined'; }

        /**
         * main function for parser
         * @param str {string} pattern to be parsed (e.g. #,##0.###).
         */
        function parsePattern(pattern, groupSep, decimalSep) {
            DECIMAL_SEP = decimalSep;
            GROUP_SEP = groupSep;

            var p = {
                minInt: 1,
                minFrac: 0,
                maxFrac: 0,
                posPre: '',
                posSuf: '',
                negPre: '',
                negSuf: '',
                gSize: 0,
                lgSize: 0
            };
            var ZERO = '0',
                DIGIT = "#";

            var parts = pattern.split(PATTERN_SEP),
                positive = parts[0],
                negative = parts[1];

            var parts = positive.split(DECIMAL_SEP),
                integer = parts[0],
                fraction = parts[1];

            console.log(parts);

            p.posPre = integer.substr(0, integer.indexOf(DIGIT));

            if (fraction) {
                for (var i = 0; i < fraction.length; i++) {
                    var ch = fraction.charAt(i);
                    console.log(ch, ZERO, DIGIT);
                    if (ch == ZERO)
                        p.minFrac = p.maxFrac = i + 1;
                    else if (ch == DIGIT)
                        p.maxFrac = i + 1;
                    else
                        p.posSuf += ch;
                }
            }

            var groups = integer.split(GROUP_SEP);
            p.gSize = groups[1] ? groups[1].length : 0;
            p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;

            if (negative) {
                var trunkLen = positive.length - p.posPre.length - p.posSuf.length,
                    pos = negative.indexOf(DIGIT);

                p.negPre = negative.substr(0, pos).replace(/\'/g, '');
                p.negSuf = negative.substr(pos + trunkLen).replace(/\'/g, '');
            } else {
                // hardcoded '-' sign is fine as all locale use '-' as MINUS_SIGN. (\u2212 is the same as '-')
                p.negPre = '-' + p.posPre;
                p.negSuf = p.posSuf;
            }

            return p;
        }


        function isString(value) { return typeof value === 'string'; }
        function isNumber(value) { return typeof value === 'number'; }

        /**
         * Format a number into a string
         * @param  {number} number       The number to format
         * @param  {{
         *           minFrac, // the minimum number of digits required in the fraction part of the number
         *           maxFrac, // the maximum number of digits required in the fraction part of the number
         *           gSize,   // number of digits in each group of separated digits
         *           lgSize,  // number of digits in the last group of digits before the decimal separator
         *           negPre,  // the string to go in front of a negative number (e.g. `-` or `(`))
         *           posPre,  // the string to go in front of a positive number
         *           negSuf,  // the string to go after a negative number (e.g. `)`)
         *           posSuf   // the string to go after a positive number
         *         }} pattern
         * @param  {string} groupSep     The string to separate groups of number (e.g. `,`)
         * @param  {string} decimalSep   The string to act as the decimal separator (e.g. `.`)
         * @param  {[type]} fractionSize The size of the fractional part of the number
         * @return {string}              The number formatted as a string
         */
        function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {

            if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';

            var isInfinity = !isFinite(number);
            var isZero = false;
            var numStr = Math.abs(number) + '',
                formattedText = '',
                parsedNumber;


            if (isInfinity) {
                formattedText = '\u221e';
            } else {
                parsedNumber = parse(numStr, '.');

                roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);


                var digits = parsedNumber.d;
                var integerLen = parsedNumber.i;
                var exponent = parsedNumber.e;
                var decimals = [];
                isZero = digits.reduce(function (isZero, d) { return isZero && !d; }, true);

                // pad zeros for small numbers
                while (integerLen < 0) {
                    digits.unshift(0);
                    integerLen++;
                }

                // extract decimals digits
                if (integerLen > 0) {
                    decimals = digits.splice(integerLen, digits.length);
                } else {
                    decimals = digits;
                    digits = [0];
                }

                // format the integer digits with grouping separators
                var groups = [];
                if (digits.length >= pattern.lgSize) {
                    groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
                }
                while (digits.length > pattern.gSize) {
                    groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
                }
                if (digits.length) {
                    groups.unshift(digits.join(''));
                }
                formattedText = groups.join(groupSep);

                // append the decimal digits
                if (decimals.length) {
                    formattedText += decimalSep + decimals.join('');
                }

                if (exponent) {
                    formattedText += 'e+' + exponent;
                }
            }
            if (number < 0 && !isZero) {
                return pattern.negPre + formattedText + pattern.negSuf;
            } else {
                return pattern.posPre + formattedText + pattern.posSuf;
            }
        }

        function parse(numStr, decimalSep) {
            var exponent = 0, digits, numberOfIntegerDigits;
            var i, j, zeros;

            DECIMAL_SEP = decimalSep;
            // Decimal point?
            if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
                numStr = numStr.replace(DECIMAL_SEP, '');
            }

            // Exponential form?
            if ((i = numStr.search(/e/i)) > 0) {
                // Work out the exponent.
                if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
                numberOfIntegerDigits += +numStr.slice(i + 1);
                numStr = numStr.substring(0, i);
            } else if (numberOfIntegerDigits < 0) {
                // There was no decimal point or exponent so it is an integer.
                numberOfIntegerDigits = numStr.length;
            }

            // Count the number of leading zeros.
            for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) {/* jshint noempty: false */ }

            if (i === (zeros = numStr.length)) {
                // The digits are all zero.
                digits = [0];
                numberOfIntegerDigits = 1;
            } else {
                // Count the number of trailing zeros
                zeros--;
                while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;

                // Trailing zeros are insignificant so ignore them
                numberOfIntegerDigits -= i;
                digits = [];
                // Convert string to array of digits without leading/trailing zeros.
                for (j = 0; i <= zeros; i++ , j++) {
                    digits[j] = +numStr.charAt(i);
                }
            }

            // If the number overflows the maximum allowed digits then use an exponent.
            if (numberOfIntegerDigits > MAX_DIGITS) {
                digits = digits.splice(0, MAX_DIGITS - 1);
                exponent = numberOfIntegerDigits - 1;
                numberOfIntegerDigits = 1;
            }

            return { d: digits, e: exponent, i: numberOfIntegerDigits };
        }

        /**
         * Round the parsed number to the specified number of decimal places
         * This function changed the parsedNumber in-place
         */
        function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
            var digits = parsedNumber.d;
            var fractionLen = digits.length - parsedNumber.i;

            // determine fractionSize if it is not specified; `+fractionSize` converts it to a number
            fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;

            // The index of the digit to where rounding is to occur
            var roundAt = fractionSize + parsedNumber.i;
            var digit = digits[roundAt];

            if (roundAt > 0) {
                // Drop fractional digits beyond `roundAt`
                digits.splice(Math.max(parsedNumber.i, roundAt));

                // Set non-fractional digits beyond `roundAt` to 0
                for (var j = roundAt; j < digits.length; j++) {
                    digits[j] = 0;
                }
            } else {
                // We rounded to zero so reset the parsedNumber
                fractionLen = Math.max(0, fractionLen);
                parsedNumber.i = 1;
                digits.length = Math.max(1, roundAt = fractionSize + 1);
                digits[0] = 0;
                for (var i = 1; i < roundAt; i++) digits[i] = 0;
            }

            if (digit >= 5) {
                if (roundAt - 1 < 0) {
                    for (var k = 0; k > roundAt; k--) {
                        digits.unshift(0);
                        parsedNumber.i++;
                    }
                    digits.unshift(1);
                    parsedNumber.i++;
                } else {
                    digits[roundAt - 1]++;
                }
            }

            // Pad out with zeros to get the required fraction length
            for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);


            // Do any carrying, e.g. a digit was rounded up to 10
            var carry = digits.reduceRight(function (carry, d, i, digits) {
                d = d + carry;
                digits[i] = d % 10;
                return Math.floor(d / 10);
            }, 0);
            if (carry) {
                digits.unshift(carry);
                parsedNumber.i++;
            }
        }

    })

答案 2 :(得分:0)

    $provide.decorator('currencyFilter', ['$delegate',
        function ($delegate) {
            var crncyFilter = $delegate;
            var extendsFilter = function () {
                var res = crncyFilter.apply(this, arguments);
                if (arguments[2]) {
                    var digi1 = arguments[2] || 2;
                    return arguments[1] + Number(arguments[0]).toFixed(digi1);
                }
                else {
                    if (arguments[1] == "¥") {
                        return arguments[1] + Number(arguments[0]).toFixed(1);
                    } 
                }

            };
            return extendsFilter;
        }]);

这是覆盖十进制数字的方法