1

I'm using a callback function after an animation, and I'm getting a result that I don't understand.

The reader's current_state should increase by 1, then the reader should move right, and then this should repeat 3 more times.

When I run the program using my web inspector, I see that the current_state does indeed increase before moving each step. However, in my browser window I only see the reader's text change values during the first step. So when the program ends, I see a 2 in the reader's text on my screen, but the value of the reader's current_state is actually 5.

To perplex me even more, I was tinkering around and added a random button with an empty click event attached. Hitting this button will make the current_state appear as the reader's text on the screen. So if I repeatedly click this button while the program runs, it looks perfect.

I'm not looking for an entirely different way to do this, as this isn't my actual code, just an example to illustrate the issue. In my code I'm trying to stick to using angular and a recursive callback function after an animation, if it's possible to fix this issue.

Thanks in advance, this has been driving me crazy!

https://jsfiddle.net/snookieordie/ns09cvqc/7/

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

app.controller("turingController", ["$scope", function ($scope) {
    $scope.reader = {
        current_state: 1,
    }

    $scope.run_program = function() {
        if($scope.reader.current_state < 5) {
            $scope.reader.current_state++;
            $(".reader").animate({"left": "+=50px"}, 1000, function() {
                $scope.run_program();
            });
        }
    }
}]); 

CSS:

.reader {
    position: relative;
    height: 50px;
    width: 50px;
    left: 0px;
    font-size: 35px;
    background-color: coral;
}

HTML:

<body ng-app="turingApp" ; ng-controller="turingController">
    <div class="reader">{{reader.current_state}}</div>
    <br/><br/>
    <input type="button" class="code_submit" value="Run Code" ng-click="run_program()" /> 
    <br/><br/>
    <input type="button" value="Empty Click Event" ng-click="" />
</body>
1

1 Answer 1

4

Use $scope.apply() just after animate call back function is being called, Below I have edited js code

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

app.controller("turingController", ["$scope", function($scope) {

  $scope.reader = {
    current_state: 1,
  }

  $scope.run_program = function() {

    if ($scope.reader.current_state < 5) {

      $scope.reader.current_state++;
      $(".reader").animate({"left": "+=50px"}, 1000, function() {
        $scope.run_program();
        $scope.$apply(); // Have added this line onlye
      });
    }
  }

}]);

Why this is needed? actually angular has watchers concept and when you are doing this complex kind of functionality watchers need to keep deep eye on variable changes, which is not present auto to achieve speed, but can be added/enhanced manually.

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

2 Comments

Amazing, thanks! Just out of curiosity, do you know why triggering the empty click event has the effect of updating the variable changes?
There are a concept of watchers. They are watching any change or event occurred. So when you click anywhere on DOM document [in browser] it is an event. Angular quickly re-generate its complete DOM. When a variable is updated with your code, watchers do not detect any change or event triggered.

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.