comma format as typing in angular
Asked Answered
D

7

5

In jqxwidget http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxnumberinput/index.htm

by default the comma’s are already in place and separated by underscore.

what i want is to have the field empty and as soon as user starts typing the comma should come as and when similarly to F2 cell render-er.

so when typed 100 is should show 100 when typed 10000 ,it should show 10,000

also i have angular in my app as we are using jqxwidget in conjucation with so any angular way is also fine

one plugin i have found does the job but when focus out not when typing https://www.npmjs.com/package/angular-numeric-directive

Devondevona answered 9/10, 2015 at 13:57 Comment(0)
S
3

Demo

<input value="100000000" id="testInput" />

Simply apply this .formatInput(numberOfCharactersForSeparator, Separator ); to your input

$(document).ready(function()
{
    $("#testInput").formatInput(3,"," );
});

using this plugin that i just made :p

$.fn.formatInput = (function(afterHowManyCharacter,commaType)
{
    if(afterHowManyCharacter && commaType != ".")
    {
        var str = $(this).val();
        var comma = commaType != undefined ? commaType : "," ;

        var strMod ;
        if($(this).val().indexOf(".") == -1)
            strMod = replaceAll(comma,"",$(this).val());
        else
        {
            strMod = replaceAll(comma,"",$(this).val());
            strMod = strMod.substring(0,strMod.indexOf("."));
        }

        if($(this).val().indexOf(".") != -1)
            $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+  $(this).val().substring($(this).val().indexOf(".")));
        else
            $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));



        var nowPos = 0;
        $(this).on("keyup",function(e)
        {
            nowPos = doGetCaretPosition($(this)[0]);
            var codePressed = e.which ;
            if(" 8 37 38 39 40 46 17".indexOf(" "+codePressed) == -1 && !e.ctrlKey)
            {
                if($(this).val().length >afterHowManyCharacter)
                {
                    strMod ;
                    if($(this).val().indexOf(".") == -1)
                        strMod = replaceAll(comma,"",$(this).val());
                    else
                    {
                        strMod = replaceAll(comma,"",$(this).val());
                        strMod = strMod.substring(0,strMod.indexOf("."));
                    }

                    if($(this).val().indexOf(".") != -1)
                        $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
                    else
                        $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));

                    if((strMod.length-1)%afterHowManyCharacter == 0)
                    {
                        setCursor($(this)[0],nowPos+1);
                    }
                    else
                    {
                        setCursor($(this)[0],nowPos);
                    }
                }
            }
        });

    }
    else if( commaType == ".")
    {
        console.log("You can't use . as Separator");
    }

    function splitByLength(str,maxLength)
    {
        var reg = new RegExp(".{1,"+maxLength+"}","g"); ;
        return reverseStringInArray(str.split("").reverse().join("").match(reg).reverse());
    }

    function replaceAll(find, replace, str) {
      return str.replace(new RegExp(find, 'g'), replace);
    }

    function reverseStringInArray(arr)
    {
        $.each(arr,function(i,val)
        {
            arr[i] = arr[i].split("").reverse().join("");
        });
        return arr ;
    }


    // Author of setCursor is nemisj
    function setCursor(node,pos)
    {
        node = (typeof node == "string" || node instanceof String) ? document.getElementById(node) : node;

        if(!node){
            return false;
        }else if(node.createTextRange){
            var textRange = node.createTextRange();
            textRange.collapse(true);
            textRange.moveEnd(pos);
            textRange.moveStart(pos);
            textRange.select();
            return true;
        }else if(node.setSelectionRange){
            node.setSelectionRange(pos,pos);
            return true;
        }

        return false;
    }

    // Author of setCursor is bezmax
    function doGetCaretPosition (oField) {

      // Initialize
      var iCaretPos = 0;

      // IE Support
      if (document.selection) {

        // Set focus on the element
        oField.focus ();

        // To get cursor position, get empty selection range
        var oSel = document.selection.createRange ();

        // Move selection start to 0 position
        oSel.moveStart ('character', -oField.value.length);

        // The caret position is selection length
        iCaretPos = oSel.text.length;
      }

      // Firefox support
      else if (oField.selectionStart || oField.selectionStart == '0')
        iCaretPos = oField.selectionStart;

      // Return results
      return (iCaretPos);
    }
});
Sika answered 13/10, 2015 at 13:23 Comment(4)
when we use decimal value the formatting is incorrectDevondevona
i did not think about the decimal let me add itSika
selected this as answer as decimal was also working fine,as well as cursor locationDevondevona
Will that commas effect to ng-model. My requirement is it should not effect to ng-model.It should be view onlyExploration
S
6

Hey I have solved this before by creating a directive that applies a filter to your HTML input. Here is a jsfiddle example

This is the directive. It both formats the user's input and keeps the cursor where the user is typing. My one issue with this is the logic behind where the cursor should be pointed.

fessmodule.directive('format', ['$filter', function ($filter) {
return {
    require: '?ngModel',
    link: function (scope, elem, attrs, ctrl) {
        if (!ctrl) return;

        var parts = attrs.format.split(':');
        attrs.foramtType = parts[0];
        attrs.pass = parts[1];

        ctrl.$formatters.unshift(function (a) {
            return $filter(attrs.foramtType)(ctrl.$modelValue, attrs.pass)
        });


        ctrl.$parsers.unshift(function (viewValue) {
            var cursorPointer = elem.context.selectionStart;
            var plainNumber = viewValue.replace(/[^\d|\-+|\.+]/g, '');
            elem.val($filter(attrs.foramtType)(plainNumber, attrs.pass));
            elem.context.setSelectionRange(cursorPointer, cursorPointer);
            return plainNumber;
        });

    }
};

And the HTML to activate it

<input type="text" ng-model="test" format="number:2" />
Sensation answered 13/10, 2015 at 15:33 Comment(2)
How are you supposed to type into the input? It doesn't let youAnachronism
This is the correct angular way to implement this feature and should be the accepted answer.Laity
P
4

Angular already provides pretty basic formatting filters like

html : {{val | number:0}}
script: $scope.val = 1234.56789;

ref:

https://docs.angularjs.org/api/ng/filter/number
https://docs.angularjs.org/api/ng/filter/currency
https://scotch.io/tutorials/all-about-the-built-in-angularjs-filters
Putrid answered 13/10, 2015 at 11:7 Comment(1)
He is asking for how to format a input field and not just html.Sensation
S
3

Demo

<input value="100000000" id="testInput" />

Simply apply this .formatInput(numberOfCharactersForSeparator, Separator ); to your input

$(document).ready(function()
{
    $("#testInput").formatInput(3,"," );
});

using this plugin that i just made :p

$.fn.formatInput = (function(afterHowManyCharacter,commaType)
{
    if(afterHowManyCharacter && commaType != ".")
    {
        var str = $(this).val();
        var comma = commaType != undefined ? commaType : "," ;

        var strMod ;
        if($(this).val().indexOf(".") == -1)
            strMod = replaceAll(comma,"",$(this).val());
        else
        {
            strMod = replaceAll(comma,"",$(this).val());
            strMod = strMod.substring(0,strMod.indexOf("."));
        }

        if($(this).val().indexOf(".") != -1)
            $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+  $(this).val().substring($(this).val().indexOf(".")));
        else
            $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));



        var nowPos = 0;
        $(this).on("keyup",function(e)
        {
            nowPos = doGetCaretPosition($(this)[0]);
            var codePressed = e.which ;
            if(" 8 37 38 39 40 46 17".indexOf(" "+codePressed) == -1 && !e.ctrlKey)
            {
                if($(this).val().length >afterHowManyCharacter)
                {
                    strMod ;
                    if($(this).val().indexOf(".") == -1)
                        strMod = replaceAll(comma,"",$(this).val());
                    else
                    {
                        strMod = replaceAll(comma,"",$(this).val());
                        strMod = strMod.substring(0,strMod.indexOf("."));
                    }

                    if($(this).val().indexOf(".") != -1)
                        $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
                    else
                        $(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));

                    if((strMod.length-1)%afterHowManyCharacter == 0)
                    {
                        setCursor($(this)[0],nowPos+1);
                    }
                    else
                    {
                        setCursor($(this)[0],nowPos);
                    }
                }
            }
        });

    }
    else if( commaType == ".")
    {
        console.log("You can't use . as Separator");
    }

    function splitByLength(str,maxLength)
    {
        var reg = new RegExp(".{1,"+maxLength+"}","g"); ;
        return reverseStringInArray(str.split("").reverse().join("").match(reg).reverse());
    }

    function replaceAll(find, replace, str) {
      return str.replace(new RegExp(find, 'g'), replace);
    }

    function reverseStringInArray(arr)
    {
        $.each(arr,function(i,val)
        {
            arr[i] = arr[i].split("").reverse().join("");
        });
        return arr ;
    }


    // Author of setCursor is nemisj
    function setCursor(node,pos)
    {
        node = (typeof node == "string" || node instanceof String) ? document.getElementById(node) : node;

        if(!node){
            return false;
        }else if(node.createTextRange){
            var textRange = node.createTextRange();
            textRange.collapse(true);
            textRange.moveEnd(pos);
            textRange.moveStart(pos);
            textRange.select();
            return true;
        }else if(node.setSelectionRange){
            node.setSelectionRange(pos,pos);
            return true;
        }

        return false;
    }

    // Author of setCursor is bezmax
    function doGetCaretPosition (oField) {

      // Initialize
      var iCaretPos = 0;

      // IE Support
      if (document.selection) {

        // Set focus on the element
        oField.focus ();

        // To get cursor position, get empty selection range
        var oSel = document.selection.createRange ();

        // Move selection start to 0 position
        oSel.moveStart ('character', -oField.value.length);

        // The caret position is selection length
        iCaretPos = oSel.text.length;
      }

      // Firefox support
      else if (oField.selectionStart || oField.selectionStart == '0')
        iCaretPos = oField.selectionStart;

      // Return results
      return (iCaretPos);
    }
});
Sika answered 13/10, 2015 at 13:23 Comment(4)
when we use decimal value the formatting is incorrectDevondevona
i did not think about the decimal let me add itSika
selected this as answer as decimal was also working fine,as well as cursor locationDevondevona
Will that commas effect to ng-model. My requirement is it should not effect to ng-model.It should be view onlyExploration
L
1

100 => 100

1000 =>1,000

10000 => 10,000

100000 => 100,000

...

10000000 => 10,000,000

10000000.540 => 10,000,000.540

I use ng-change event to make this example

        // on-change event
        $scope.ngchanged = function (val) {
            $scope.iputval = numberWithCommas(val);
        };

        function numberWithCommas(n) {

            while (n.toString().indexOf(",") != -1)
            {
                n = n.replace(",", "");
            }
            var parts = n.toString().split(".");
            return parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
        }

Use it

<input type="text" ng-model="iputval" ng-change="ngchanged(iputval)" />

Updated add demo and code by following link

Full code and demo >> here

Lavettelavigne answered 20/10, 2015 at 4:32 Comment(0)
F
1
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('app',[]);
app.controller('myCtrl',function($scope){
    $scope.name = "1232.33";
    $scope.changeFormat = function(value){
        $scope.name = Number(value).toLocaleString('en');
    }
 });
</script>
<body>
    <div ng-app="app" ng-controller="myCtrl">

    <p>Input something in the input box:</p>
    <p>Number: <input type="text" ng-model="name" placeholder="Enter name here" ng-blur="changeFormat(name)"></p>
    <h1>Formatted value {{name}}</h1>

 </div>

 </body>
 </html>
Fitful answered 20/10, 2015 at 4:55 Comment(0)
N
1

Here is a hackish solution. The idea is to watch for changes in the input text and format the input accordingly.

HTML

<div ng-controller="so">
  <input ng-model="salary"></input>
</div> 

Javascript

app.controller('so', function($scope) {
$scope.salary = '12567';
$scope.$watch('salary', function(){
    // strip out all the commas and dots
    var temp = $scope.salary;
    if (!temp) return; // ignore empty input box
    var lastChar = temp[temp.length-1];
    if (lastChar === ',' || lastChar === '.') // skip it/allow commas
        return;
    var a = temp.replace(/,/g,'');  //remove all commas
    //console.log(a);
    if (isNaN(a)) 
        $scope.salary = temp.substring(0, temp.length-1); // last char was not right
    else {
        var n = parseInt(a, 10); // the integer part
        var f = ''; // decimal part
        if (a.indexOf('.') >= 0) // decimal present{
            if (lastChar === '0') // 0's after decimal point are OK
                return;
            f = ('' + parseFloat(a)).substr(a.indexOf('.'));
        }
        var formatted_salary = '';
        var count = 0;
        var ns = '' + n; // string of integer part
        for (var i=ns.length-1; i>=0; i--) {
            if (count%3===0 && count>0)
                formatted_salary = ',' + formatted_salary;
            formatted_salary = ns[i] + formatted_salary;
            count += 1;
        }
        formatted_salary = formatted_salary + (f ? f : '');
        $scope.salary = formatted_salary;

    }
})
})

Here is the JSFiddle It gracefully handles things like

  1. won't allow any characters other than numbers , and .
  2. multiple commas and dots formatted correctly

PS:- you might want to handle the proper positioning of the caret yourself using text range. I haven't included that here.

Nelrsa answered 20/10, 2015 at 6:25 Comment(3)
Do you want commas in the decimals also? That would be strange. Other than that decimals are working. If not, could you please give the number which is not working?Nelrsa
also when having decimal values the cursor moves to the end if we change any value..this way user can not enter valuesDevondevona
Yes, thanks. That was a bug. It's fixed now. Please give an upvote if you liked the answer. (The text range is a little harder to do - it's a common problem #20203716)Nelrsa
R
0

Please check out ng-number-input

I think it accomplishes the task easily.

https://www.npmjs.com/package/ng-number-input

I made it for my project and I thought I'd share it with the community.

Source code available on git hub and link is available in npm page.

Rasorial answered 12/3, 2022 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.