Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Format number Vue directive
export default {
install: Vue => Vue.filter('format-number', (value, { thousand = ' ', decimal = '.', decimals = null, maxDecimals = decimals, minDecimals = decimals, normalize = true, roundToEven = true } = {}) => {
value = normalize ? normalizeNumber(value) : `${value != null ? value : ''}`;
let pieces = value.split('.');
if (!pieces[0].length) {
return;
}
if (minDecimals > 0) {
pieces[1] = (pieces[1] = pieces[1] || '').padEnd(minDecimals, '0');
}
if (maxDecimals != null && maxDecimals >= 0 && (pieces[1] || '').length > maxDecimals) {
const digit = +pieces[1][maxDecimals];
pieces[1] = pieces[1].slice(0, maxDecimals);
let digits = pieces.join('');
if (digit > 5 || (digit === 5 && (!roundToEven || (digits.slice(-1) & 1)))) {
digits = digits.replace(/([^-9]?)(9*)$/, (_, digit, nines) => `${++digit}${''.padEnd(nines.length, '0')}`);
const length = digits.length - maxDecimals;
pieces = [digits.slice(0, length), digits.slice(length)];
}
if (!maxDecimals) {
pieces.pop();
}
}
pieces[0] = pieces[0].replace(/\d(?=(?:\d{3})+$)/g, `$&${thousand}`);
return pieces.join(decimal);
})
};
function normalizeNumber (value, { isDecimal = true, isUnsigned = false, decimalSeparator = '.' } = {}) {
if (!(value = value != null && `${value}`)) {
return '';
}
const isNegative = /^\s*-/.test(value) && !isUnsigned;
value = value.replace(isDecimal ? /[^\d,.]/g : /\D/g, '');
if (isDecimal) {
const pieces = value.split(/[,.]/);
const decimal = pieces.pop().replace(/0+$/, '');
if (pieces.length) {
value = `${pieces.join('') || (decimal ? '0' : '')}${decimal ? `${decimalSeparator}${decimal}` : ''}`;
}
}
value = value.replace(/^(?:0(?!\b))+/, '');
if (isNegative) {
value = value ? `-${value}` : '';
}
return value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment