1

I'm new to Angular JS and I want to bind the input value to $scope object, just like we use ng-bind and ng-model for input fields to bind their values to DOM (the value changes as we type something in the input).

Can't I do the same? I mean just like displaying live text entered into input should be stored to $scope.foo.bar and hence it is printed in the console?

Here's what I'm trying:

<script type="text/javascript">
    var app = angular.module("testApp", []);
    app.service("stringService", function(){
        this.myFunction = function(word){
            return word.toUpperCase();
        };
    });
    app.controller("control", function($scope, $location, stringService, $http){
        $scope.age=24;
        $scope.foo = {bar: "hello"};
        console.log($scope.foo.bar);
        $scope.isNumber = angular.isNumber($scope.foo.bar);
    });

</script>

<div ng-app="testApp">
    <div ng-controller="control" ng-init="obj=[{name:'vikas'}, {name: 'vijay'}, {name: 'vinay'}]; mySwitch=true">
        <form name="testForm">
            <input type="text" name="bar" ng-model="foo.bar" required>
        </form>
        <div>{{isNumber}}</div>
    </div>
</div>

I can see the initial value (hello) in the console and false in DOM. But it doesn't update.

2
  • Is there any other code which might be modifying foo? Commented Jun 2, 2017 at 3:30
  • Your code seems to be working fine. what exactly are you trying to do? Commented Jun 2, 2017 at 3:43

3 Answers 3

1

this line $scope.isNumber = angular.isNumber($scope.foo.bar); will only run once which is at angular initialize the page.

you can change isNumber to function in order to call multiple times.

$scope.isNumber = function() {
  return angular.isNumber($scope.foo.bar);
}

call it at template:

<div>{{isNumber()}}</div>    

var app = angular.module("testApp", []);
app.service("stringService", function() {
  this.myFunction = function(word) {
    return word.toUpperCase();
  };
});
app.controller("control", function($scope, $location, stringService, $http) {
  $scope.age = 24;
  $scope.foo = {
    bar: 1
  };
  console.log($scope.foo.bar);
  $scope.isNumber = function() {
    console.log(Number.isFinite($scope.foo.bar));
    console.log(typeof($scope.foo.bar));
    return angular.isNumber($scope.foo.bar);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="testApp">
  <div ng-controller="control" ng-init="obj=[{name:'vikas'}, {name: 'vijay'}, {name: 'vinay'}]; mySwitch=true">
    <form name="testForm">
      <input type="text" name="bar" ng-model="foo.bar" required>
    </form>
    <div>{{isNumber()}}</div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

14 Comments

"this line $scope.isNumber = angular.isNumber($scope.foo.bar); will only run once". isNumber() would also fire only once? Do I need to use ng-change like Parth suggested?
@VikasKumar no, if you bind function in template, it will be fired every time in angular's digest cycle.
Just tried. It doesn't. Just shows output for initial value.
Further it is showing false for every possible value, even for a string :O
Okay. The function fires every time I change it. But it returns false even for a number after I change initial value?
|
1

while @Pengyy's is quite correct in saying that you need to databind to a function, that is only part of the problem...

The problem is NaN, a perplexing numeric value that is not a number, but has type 'number' and some quicks having to do with bindings to string valued attributes like <input>'s value in html.

// the constant NaN
console.info(NaN);
// the type of the constant NaN
console.info(typeof NaN);
// NaN is not equal to NaN 
console.info(NaN === NaN);
// Number.isNaN checks for NaN
console.info(Number.isNaN(NaN));
// Number.isNaN returns false for any value unless typeof value === 'number'
console.info(Number.isNaN({
  a: []
}));

surprisingly, Angular's angular.isNumber function does not help us deal with these oddities. As stated in the documentation it

Determines if a reference is a Number. This includes the "special" numbers NaN, +Infinity and -Infinity. If you wish to exclude these then you can use the native `isFinite' method.

Ref: https://docs.angularjs.org/api/ng/function/angular.isNumber

To make matters worse, it also ignores all values for which typeof value !== 'number'

Finally, the last hurdle to overcome is that an HTML input's value is always a string! This means we need to convert it to number.

Therefore, the function needs to look like

$scope.isNumber = function(n) {
  // must convert to number because `Number.isNaN` does not coerce
  return isFinite(n) && !Number.isNaN(Number(n));
}

And the binding like

<div>{{isNumber(foo.bar)}}</div>

Here is an example

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
  (function() {
    "use strict";

    var app = angular
      .module("testApp", [])
      .controller({
        MyController
      });

    MyController.$inject = ['$scope'];

    function MyController($scope) {
      $scope.foo = {
        bar: "hello"
      };
      console.log($scope.foo.bar);
      $scope.isNumber = function(n) {
        console.info(typeof n);
        return isFinite(n) && angular.isNumber(Number(n));
      }
    }
  }());
</script>

<div ng-app="testApp">
  <div ng-controller="MyController">
    <form name="testForm">
      <input type="type" name="bar" ng-model="foo.bar" required>
    </form>
    <div>{{isNumber(foo.bar)}}</div>
  </div>
</div>

Notice how the raw type of the input is always 'string'

Comments

0

Value must be updating but you do not have anything to communicate, You need a watcher or a function that fires the console log and checks for number.

Change your controller to :-

 app.controller("control", function($scope, $location, stringService, $http){
            $scope.age=24;
            $scope.foo = {bar: "hello"};
            console.log($scope.foo.bar);
            $scope.isNumber = angular.isNumber($scope.foo.bar);
            $scope.check = function() {
                $scope.isNumber =  angular.isNumber($scope.foo.bar);
                console.log($scope.foo.bar);
                console.log($scope.isNumber);
            }
        });

And in Html

<input type="type" name="bar" ng-model="foo.bar" ng-change="check()" required>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.