4

I have an angular object item.add_value = 0 bind into the

<input type="number" ng-model="item.add_value"   ng-change="sumUp(item)" min="0" max="10000000000" />

In order to do the calculation I have to use type="number" not type="text"

Then my question is how to hide the content of the input when the value is 0?

Ricc
  • 321
  • 3
  • 6
  • 15
  • Converting strings to numbers in JavaScript is trivial. As to your second question: I'm not of the opinion that this is a good idea. Why wouldn't you want to display the value if it equals zero? – Blazemonger Oct 23 '14 at 21:45

7 Answers7

7

I just had this same problem and found a way to fix/improve on @dubadub's answer, so I'm sharing my version of his directive:

.directive('hideZero', function() {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$formatters.push(function (inputValue) {
                if (inputValue == 0) {
                    return '';
                }
                return inputValue;
            });
            ngModel.$parsers.push(function (inputValue) {
                if (inputValue == 0) {
                    ngModel.$setViewValue('');
                    ngModel.$render();
                }
                return inputValue;
            });
        }
    };
})

You just use it by adding the hide-zero attribute to your inputs.

R. Kazeno
  • 111
  • 1
  • 2
  • 4
  • This is the better solution as the cursor remains (setting text-indent you lose the cursor), and you don't modify the actual value (we just want to change was is displayed, not the underlying model). – monty Sep 11 '17 at 03:17
4

The simplest (and the weirdest) way to do it is to use ... CSS! Consider this:

<input type="number" ng-model="item.add_value" 
        ng-class="{zero: item.add_value === 0}"
        ng-change="sumUp(item)" 
        min="0" 
        max="10000000000" />

and CSS:

.zero {
   text-indent: -7px;   
}

Not sure it will be appropriate for you, but this is definitely fun and can work if you adjust indent for your font size and input padding.

Demo: http://plnkr.co/edit/2gRzdY7DVwrPdNGoD0Fq?p=preview

UDP. One more version using directive:

.directive('hideZero', function() {
    return {
        link: function(scope, element) {
            element.on('input change', function() {
                if (this.value === '0') {
                    this.value = '';
                }
            })
        }
    };
});

and use it like:

<input type="number" ng-model="item.add_value" 
       ng-change="sumUp(item)" 
       hide-zero
       min="0" 
       max="10000000000" />

Demo: http://plnkr.co/edit/nrE3vEW2NSuLYeZuKIjO?p=preview

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • Yes, that's why I said this is simplest approach. If it was not a 1am I would try to make a directive with `$parsers` and `$formatters`. This is how you should attempt to solve this problem. – dfsq Oct 23 '14 at 21:49
  • @Ricc Here is one more simple version with custom directive: http://plnkr.co/edit/nrE3vEW2NSuLYeZuKIjO?p=preview – dfsq Oct 23 '14 at 22:00
  • I am not so sure about the syntax but in the is hide-zero but in the directive is call 'hideZero'? so directive will the Cap letter and auto separate the word? – Ricc Oct 24 '14 at 00:09
  • Yes, in HTML you use snake-case, but in javascript it's translated to camelCase. – dfsq Oct 24 '14 at 05:42
  • Do you mind answer this question for me ? https://stackoverflow.com/questions/26552647/compare-array-value-after-sort-angular-js – Ricc Oct 24 '14 at 17:04
  • I find that if the model value is defined ($scope.item=[]; $scope.item.add_value=0 ) in the app this solution does not work. – Harvey Mushman Mar 21 '16 at 22:31
2

I think, the most best approach is in using ngModelController because it is not uses DOM (we just in data layer, not in view, we need bind as usual except 0) and very strait-forward. It helps adjust binding between model and it's view in way we need:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
    $scope.name = 'World';
});

app.directive('hideZero', function() {
    return {
        require: 'ngModel',
         link: function(scope, element, attrs, modelCtrl) {

           modelCtrl.$parsers.push(function (inputValue) {

             if (inputValue === 0) {
               return '';
             }         

             return inputValue;         
           });
         }
    }
});

See more https://docs.angularjs.org/api/ng/type/ngModel.NgModelController.

Working plunker http://plnkr.co/edit/Zatou8lLx23xwXd1x9hd?p=preview.

dubadub
  • 3,312
  • 3
  • 23
  • 28
  • thanks for the Answer, but I think @dfsq 's solution is what I try to get, urs is a bit inversed – Ricc Oct 23 '14 at 23:57
  • Do you mind answer this question for me ? https://stackoverflow.com/questions/26552647/compare-array-value-after-sort-angular-js – Ricc Oct 24 '14 at 17:04
1

You could use ng-show or ng-hide depending on how you want the semantics.

I would recommend ng-hide, because its more intuitive and semantic in my opinion:

 <input type="number"
        ng-hide="item.add_value == '0'"
        ng-model="item.add_value"
        ng-change="sumUp(item)"
        min="0" 
        max="10000000000" />

but you could use:

ng-show:

 <input type="number"
        ng-show="item.add_value != '0'"
        ng-model="item.add_value"
        ng-change="sumUp(item)"
        min="0" 
        max="10000000000" />
agconti
  • 17,780
  • 15
  • 80
  • 114
  • But if you do ng-hide, it will hide the whole input right? I only want to hide the 0 value. And my calculation doesnt work after add in "ng-if" I think that will recreate the object which let item.add_value lose its refferece – Ricc Oct 23 '14 at 21:36
  • @Ricc right, it would hide the entire input element. – agconti Oct 23 '14 at 21:38
  • What do you mean by hide only the zero value? – agconti Oct 23 '14 at 21:38
  • 1
    The correct solution, I think, is to trap the error when you perform the calculation. – Blazemonger Oct 23 '14 at 21:48
1

var app = angular.module('app', []);

app.controller('firstCtrl', function($scope) {

  $scope.item = {
    add_value: 0
  };

  $scope.$watch('item.add_value', function() {
    if ($scope.item.add_value === 0) {
      $scope.item.add_value = "";

    }

  });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app">
  <div ng-controller="firstCtrl">
    <input type="number" ng-model="item.add_value" ng-change="sumUp(item)" min="0" max="10000000000" />


  </div>
</div>
sylwester
  • 16,498
  • 1
  • 25
  • 33
0

Actually the easiest solution would be setting the min value to > 0 like 10?

<input type="number" ng-model="item.add_value" ng-change="sum_Up(item)" min="10" max="10000000000" /> <br />
Ricc
  • 321
  • 3
  • 6
  • 15
0

I let it be string, but parse it when calculating:

<input type="number" ng-model="item.add_value"   ng-change="sumUp(item)" min="0" max="10000000000" />
{{total}}

JS:

var getRealValue = function(val){
    if(val === ''){
        return 0;
    }else{
        return parseFloat(val);
    }
};
$scope.sumUp = function(val){
   $scope.total = getRealValue(val);
};
George I.
  • 560
  • 2
  • 7
  • 26