Money formatting directive in Angular
<p>I need a directive for filtering a field for currency, so a user just needs to type and the decimal is implied.</p>

<p>Needs:</p>

<ol>
<li>Format decimal field as user types  - </li>
</ol>

<p><strong>Start at the hundredths place as the user types. So they would type "4" and see "0.04", type "42" and see "0.42", type 298023 and see "2980.23"</strong></p>

<ol start="2">
<li>Field must be a number</li>
<li>Must allow negatives <code>-</code></li>
<li>Allow 0.00 as a number input</li>
<li>Ideally would use type="number" but "type=text" is okay</li>
<li>You should be able to clear the field to be empty. </li>
</ol>

<p>The ng-currency filter does not fulfill these requirements as is. Please see behaviour in plunkers to see what I mean.</p>

<p>My <a href="http://plnkr.co/edit/GZhVaNaMcewii8jN3oUn?p=preview" rel="nofollow">First Plunker</a> has `input = text' and allows negative numbers. One problem is that you cannot type a negative as the very first number. When you clear the field, it returns to '0.00' but it should completely clear.</p>

<pre><code>   app.directive('format', ['$filter', function ($filter) {
 return {
            require: 'ngModel', //there must be ng-model in the html
            link: function (scope, elem, attr, ctrl) {
                if (!ctrl) return;

                ctrl.$parsers.unshift(function (viewValue, modelValue) {
                    var plainNumber = viewValue.replace(/[^-+0-9]/g,'');
                    var newVal = plainNumber.charAt(plainNumber.length-1);
                    var positive = plainNumber.charAt(0) != '-';
                    if(isNaN(plainNumber.charAt(plainNumber.length-1))){
                      plainNumber = plainNumber.substr(0,plainNumber.length-1)
                    }
                    //use angular internal 'number' filter
                    plainNumber = $filter('number')(plainNumber / 100, 2).replace(/,/g, '');
                    if(positive &amp;&amp; newVal == '-'){
                      plainNumber = '-' + plainNumber;
                    }
                    else if(!positive &amp;&amp; newVal == '+'){
                      plainNumber = plainNumber.substr(1);
                    }
                    plainNumber.replace('.', ',');

                    //update the $viewValue
                    ctrl.$setViewValue(plainNumber);
                    //reflect on the DOM element
                    ctrl.$render();
                    //return the modified value to next parser
                    return plainNumber;
                });
            }
        };

}]);
</code></pre>

<p>My <a href="https://plnkr.co/edit/uc9djyvy0SrIG9RF7Fbh?p=preview" rel="nofollow">Second Plunker</a> has <code>input = text</code> and allows for negative input. Like the first plunker, it won't allow a negative as the first character, only after numbers are typed. The second is that it starts at the tenths place instead of the hundredths. (if you type '3' you should see '0.03' but here it shows '0.3')</p>

<pre><code>app.directive('inputRestrictor', [function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModelCtrl) {
            var pattern = /[^.0-9+-]/g;

            function fromUser(text) {
                if (!text)
                return text;

                var rep = /[+]/g;
                var rem = /[-]/g;
                rep.exec(text);
                rem.exec(text);

                var indexp = rep.lastIndex;
                var indexm = rem.lastIndex;
                text = text.replace(/[+.-]/g, '');
                if (indexp &gt; 0 || indexm &gt; 0) {
                    if (indexp &gt; indexm) text = "+" + text; // plus sign?
                    else text = "-" + text;
                }

                var transformedInput = text.replace(pattern, '');
                transformedInput = transformedInput.replace(/([0-9]{1,2}$)/, ".$1")
                ngModelCtrl.$setViewValue(transformedInput);
                ngModelCtrl.$render();
                return transformedInput;
            }

            ngModelCtrl.$parsers.push(fromUser);
        }
    };
}]);
</code></pre>

<p>How can I reconcile these solutions or tailor one to meet the requirements? I want to avoid extra libraries or add-ons. I have been told that the best approach would be to study the source for the currency filter, and recreate that filter with the additional requirements.I would love to do this, but I really don't have the skills for it right now. These two directives are what I have. </p>