$scope.$watch - What am I doing wrong


#1

I guess I’m probable being really daft but I just can’t seem to get this really simple stuff to work. I’m working on an app that relies on a few sliders that are used to calculate a total grade. I’m stuck on the basic functionality of having the total be updated when any one of the sliders is changed. I’ve put the basic stuff onto CodePen and tried to clean up the code and remove anything that wasn’t just about this bit.

http://codepen.io/urbanmania/pen/IqGfF/?editors=101

I guess I should say I’m no JavaScript expert, was just toying with the idea of taking an iOS native app I did some time ago and convert to HTML5. So sorry if I’m just being thick!


#2

this took me a minute also, but it helped to refactor the sliders to directives.


#3

What’s getting you is “SCOPE”. When you put those slider values on the $scope like :

  $scope.s1 = 5;
  $scope.s2 = 5;

You are using “primitives”. Basically it means these are non-complex simple strings. That gets put on the view just fine. Since the view is linked to them, when you see the slider moving, the value on the view also changes.

However, because they were primitives, they are really just copies of “5”. So, the $scope in the controller is no longer linked to them. When they change on the view, the controller sees nothing different; so, your $watch never triggers a change. Hence, the grade doesn’t updated.

This is a very common problem with early AngularJS (and general JavaScript) developers.

To solve this, a good rule of thumb is NEVER use primitives (simple strings) in your $scope. Instead use objects/array with “dot notation”.

In depth explanation : https://github.com/angular/angular.js/wiki/Understanding-Scopes

Here is a working sample for you:


#4

Thanks so much! Makes total sense now, hindsight and all that…


#5

Thanks, was helpful to have a look at the directives although Calendee gave a simpler version.


#6

He took me to school! :smiley: