0

Just started learning AngularJS. I was trying to understand the two-way data binding by writing a code that adds two numbers from the input boxes. Here's what I have written:

HTML

 <div ng-app="cal">
    <div  ng-controller="calc">
    <input type="text" ng-model="a"/>
    <input type="text" ng-model="b"/>
    <span>{{result}}</span>
    </div>
    </div>

JavaScript

   var app=angular.module("cal", []);
        app.controller("calc",function ($scope) {
        $scope.result=Number($scope.a || 0)+ Number($scope.b || 0);
      });

This, however, doesn't give the intended result i.e "result" is not updated automatically.

But the following code works:

HTML

<div ng-app="cal">
<div  ng-controller="calc">


<input type="text" ng-model="a" ng-keyup="add()"/>
<input type="text" ng-model="b" ng-keyup="add()"/>

<span>{{result}}</span>
</div>
</div>

JavaScript

  app.controller("calc",function ($scope) {
   $scope.add=function(){
        $scope.result=Number($scope.a || 0)+ Number($scope.b || 0);
    }
  });

Why do I need the "keyup" directive? Shouldn't the variable "result" be updated automatically as the values in the fields change?

I also created a jsfiddle here: https://jsfiddle.net/Deadboy/m9ket0sL/

1
  • @AdamWolski what if value isn't an integer? Commented Dec 3, 2016 at 16:02

2 Answers 2

2

No, it shouldn't. The controller function is executed once, when angular sees the ng-controller in the DOM. It's not executed every time you type something in the input boxes. So the code computing the result is only executed once, before the user has had a chance to type anything in the inputs.

You don't need the keyup, though (and that wouldn't work if you pasted the value with your mouse, BTW). All you need is

$scope.add = function(){
     return (Number($scope.a || 0)+ Number($scope.b || 0));
}

and in the view:

<span>{{ add() }}</span>

When doing it that way, angular will reevaluate the add() expression after each event that modifies the model, and update the DOM with the result of the expression.

If you want to compute the result only when a or b changes, you should be using ng-change, not ng-keyup.

Note that if your inputs are supposed to contain numbers only, you should use an input of type number, not text. In that case, $scope.a and $scope.b will be of type number, not string.

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

8 Comments

Why does returning from the function and binding the function "add" to the view work but not binding the variable "result" directly? Doest Angular watch for changes only in the functions?
No, it watches attribute values too. But the attribute result is initialized once and only once: when the controller is instanciated. So its value never changes, so ANgular doesn't detect any change: there is none.
I'm sorry but I still don't understand completely. I understand that the value of the variable gets fixed at the time of initialization but how does enclosing it in a function help?
When you add {{ foo() }} in your template, angular watches this expression. That means that every time it launches its change detection, it reevaluates the value of foo(), and updates the DOM accordingly. So, every time you type something in one of the inputs, angular populates the ngModel, then triggers a change detection, which reevaluates the value of foo(), and updates the DOM with the new value returned by foo(). You can see it as a function in a cell of an Excel worksheet. Every time you change values in the worksheet, the function is reevaluated, and its result is displayed in the cell.
You said that it watches attribute values too so why doesn't it reevaluate "$scope.result" every time and propagate the changes to DOM?
|
1

scope variable (a) and (b) are being updated since they are two-way binded.

variable a1 and b1 won't get the update since they only get updated when you initiate your controller "calc" and they are not two-way binded.

To update your result scope variable you can use ng-change to set variable a1 and b1 with updates from $scope.a and $scope.b

<div ng-app="cal">
<div  ng-controller="calc">


<input type="text" ng-model="a" ng-change="updateResult()"/>
<input type="text" ng-model="b" ng-change="updateResult()"/>

<span>{{result}}</span>
</div>

/**
 * Created by rajat on 12-Nov-16.
 */
var app=angular.module("cal", []);


app.controller("calc",function calc($scope) {
    $scope.updateResult = function () {
      var a1 = Number($scope.a || 0);
      var b1 = Number($scope.b || 0);
      $scope.result=a1+b1;
    }
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.