Reputation: 749
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.
Upvotes: 1
Views: 1917
Reputation: 31803
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'
Upvotes: 1
Reputation: 38161
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>
Upvotes: 1
Reputation: 545
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>
Upvotes: 0