How can I use an AngularJS filter to format a number to have leading zeros?

JavascriptAngularjs

Javascript Problem Overview


I checked the documentation. What I would like is for my numbers to have four digits and leading zeros.

22 to 0022
1  to 0001

Can someone help and tell me if this is possible with the number or another kind of filter?

Javascript Solutions


Solution 1 - Javascript

No filter required, Just use an expression in your html

{{("00000"+1).slice(-6)}}      // '000001'

{{("00000"+123456).slice(-6)}} // '123456'

Solution 2 - Javascript

Let's say you have a module called myModule in your app myApp:

angular.module('myApp', ['myModule']);

Define your filter in in this module:

angular.module('myModule', [])
    .filter('numberFixedLen', function () {
        return function (n, len) {
            var num = parseInt(n, 10);
            len = parseInt(len, 10);
            if (isNaN(num) || isNaN(len)) {
                return n;
            }
            num = ''+num;
            while (num.length < len) {
                num = '0'+num;
            }
            return num;
        };
    });

Use your filter in markup:

{{myValue | numberFixedLen:4}}

Solution 3 - Javascript

Keeping it minimal... (works with both strings & numbers) Do some validation if you have to (isNumber, NaN)

// 1e8 is enough for working with 8 digits (100000000)
// in your case 1e4 (aka 10000) should do it
app.filter('numberFixedLen', function () {
	return function(a,b){
		return(1e4+""+a).slice(-b);
	};
});

If you want it even smaller and the browser supports arrow function or you are using babel/traceur then it could be reduced to:

app.filter('numberFixedLen', () => (a, b) => (1e4 + "" + a).slice(-b))

html:

{{ myValue | numberFixedLen:4 }}

Note This has less flexibility and this will only work for numbers lower then 10000 if it's a bigger number you would have to increase both 4 and 1e4 or use any other dynamic solution.
This was intended to do as little as possible as fast as possible.

It is intentionally the same thing as doing:

("10000"+1234567).slice(-4) // "4567"
("10000"+1234567).slice(-9) // "001234567"

Update You could also use padStart (but it doesn't work in IE)

// app.filter('numberFixedLen', () => (a, b) => ("" + a).padStart(b, 0))

console.log("1234567".padStart(4, 0)) // "1234567"
console.log("1234567".padStart(9, 0)) // "001234567"

Solution 4 - Javascript

Minimum code with underscore.string's padding function and the angular-underscore-string filter:

working demo in jsFiddle


> angular string input -> angular-underscore-string filter -> underscore.string

<div ng-app="app" ng-controller="PadController">
   <div ng-repeat="num in nums">{{ num | s: 'pad':[4, '0'] }}</div>
</div>

angular.module('app', ['underscore.string']).controller('PadController', function ($scope) {
    $scope.nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
});

// 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15

The s variable refers to the string library. In older versions you might have to substitute it for "_.str", ie. {{ num | _.str: 'pad':[4, '0'] }}

Solution 5 - Javascript

If you are dealing exclusively with "0" padding and don't mind tailoring your filters by use case, I'd go with something similar to Endless's answer for speed but would recommend you make sure the number isn't already long enough with something like:

app.filter('minLength', function () {
    return function(input,len){
        input = input.toString();
        if(input.length >= len) return input;
        else return("000000"+input).slice(-len);
    }
}); 

As this will not only save it from trimming numbers or strings that already satisfy the minimum length which is important to avoid weird stuff like:

{{ 0.23415336 | minLength:4 }} //Returns "0.23415336" instead of "5336" like in Endless's code

But by using "000000" instead of a number like 1e6 you avoid both changing the actual value of the input (by not adding 1000000 to it) and avoid the need to implicitly convert the number to a string thereby saving a computational step considering the input would already be a converted to a string to avoid the clipping issue mentioned above.

If you want a system that doesn't need any use-case testing that's both faster and more flexible than bguiz's solution I use a filter like:

app.filter('minLength', function(){
  return function(input, len, pad){
    input = input.toString(); 
    if(input.length >= len) return input;
    else{
      pad = (pad || 0).toString(); 
      return new Array(1 + len - input.length).join(pad) + input;
    }
  };
});

This allows you to do the standard:

{{ 22 | minLength:4 }} //Returns "0022"

But also gives you the option to add non-zero padding options like:

{{ 22 | minLength:4:"-" }} //Returns "--22"

and you can enforce wacky stuff with numbers or strings like:

{{ "aa" | minLength:4:"&nbsp;" }} //Returns "  aa"

Plus, if the input is already longer than your desired length, the filter will just pop it back out without any trimming:

{{ 1234567 | minLength:4 }} //Returns "1234567"

You also avoid the need to add validation for len because when you call the filter without a len argument, angular will throw a RangeError in your console at the line where you try to create an array of length null making it simple to debug.

Solution 6 - Javascript

You could just use pure JavaScript such as

('00000'+refCounter).substr(-5,5)

for padding with 5 zeros the value of refCounter.

NOTE: Make sure to check that refCounter is not undefined, otherwise you'll get an exception.

Solution 7 - Javascript

Pls use the below filter modify if required for some modifications

  app.filter('customNo', function () {
            return function (input) {
                var n = input;
                return (n < 10) ? '000' + n : (n < 100) ? '00' + n : (n < 1000) ? '0' + n : '' + n;
            }
        });


<span>{{number|customNo}}</span>

Solution 8 - Javascript

Another example:

// Formats a number to be at least minNumberOfDigits by adding leading zeros
app.filter('LeadingZerosFilter', function() {
  return function(input, minNumberOfDigits) {
    minNumberOfDigits = minNumberOfDigits || 2;
    input = input + '';
    var zeros = new Array(minNumberOfDigits - input.length + 1).join('0');
    return zeros + input;
  };
});

Solution 9 - Javascript

The cleanest would be to create your own filter in angular and use it. There's already a few answers for this but personally I find this easiest to read. Create a array by the length of zeros needed then join the array with zero.

myApp.filter('customNumber', function(){
    return function(input, size) {
        var zero = (size ? size : 4) - input.toString().length + 1;
        return Array(+(zero > 0 && zero)).join("0") + input;
    }
});

Use it like:

{{myValue | customNumber}}

I also made it so you can specify leading zeros as a parameter:

{{myValue | customNumber:5}}

Demo: http://www.bootply.com/d7SbUz57o8

Solution 10 - Javascript

This is an Angular 1.x variant of the directive in TypeScript which would handle both integers and decimals. Everything is considered 'type safe' thanks to TS.

adminApp.filter("zeroPadNumber",
    () => (num: number, len: number): string => {
        if (isNaN(num) || isNaN(len)) {
            return `${num}`;
        }
        if (`${num}`.indexOf(".") > -1) {
            var parts = `${num}`.split(".");
            var outDec = parts[0]; // read the before decimal
            while (outDec.length < len) {
                outDec = `0${outDec}`;
            }
            return outDec + parts[1]; // reappend the after decimal
        } else {
            var outInt = `${num}`;
            while (outInt.length < len) {
                outInt = `0${outInt}`;
            }
            return outInt;
        }
    });

Solution 11 - Javascript

I've extended @bguiz's answer to be able to handle arrays, which was my requirement for using the filter on ng-options:

app.filter('numberFixedLen', function () {
  return function (p, len) {
    function toFixedLength(n, len) {
      var num = parseInt(n, 10);

      len = parseInt(len, 10);

      if (isNaN(num) || isNaN(len)) {
        return n;
      }

      num = '' + num;

      while (num.length < len) {
        num = '0' + num;
      }

      return num;
    }

    if (p.length) {
      for (var i = 0; i < p.length; i++) {
        p[i] = toFixedLength(p[i], len);
      }
    } else {
      p = toFixedLength(p, len);
    }

    return p;
  };
});

Solution 12 - Javascript

Example code:

{{ (value > 9 ? (value > 99 ? (value > 999 ? value : '0'+value) : '00'+value) : '000'+value) }}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlan2View Question on Stackoverflow
Solution 1 - JavascriptallenhwkimView Answer on Stackoverflow
Solution 2 - JavascriptbguizView Answer on Stackoverflow
Solution 3 - JavascriptEndlessView Answer on Stackoverflow
Solution 4 - JavascriptBenny BottemaView Answer on Stackoverflow
Solution 5 - JavascriptmakewavesnotwarView Answer on Stackoverflow
Solution 6 - JavascriptMarcoView Answer on Stackoverflow
Solution 7 - JavascriptAjay BeniwalView Answer on Stackoverflow
Solution 8 - JavascriptlananView Answer on Stackoverflow
Solution 9 - JavascriptArne H. BitubekkView Answer on Stackoverflow
Solution 10 - JavascriptJames GrayView Answer on Stackoverflow
Solution 11 - JavascriptflxView Answer on Stackoverflow
Solution 12 - JavascriptSathi sHView Answer on Stackoverflow