Tom Sykes
Tom Sykes

Reputation: 161

Ionic: AngularJS Variables not Updating DOM with $scope

I've got an object that is dynamically updated to represent the currently playing track in my Ionic app, such that the visual feedback is the currently playing track art and title. This function works absolutely fine and I know it updates correctly because the interface is updated every time I press a button to skip to the next track.

However, I've added in a setInterval() so that tracks can advance automatically and now the interface does not update each time a track advances. The variables are updating in the $scope correctly, because I can hear the correct tracks playing, but interface elements do not update to match.

Is this a DOM problem? Does Ionic do this automatically on button presses? I just don't understand how the same code wouldn't work when running on a timer instead of requiring user input.

JS:

function advance() {
        var i = currentIndex;

        $scope.stop();
        if (i < 4) {
            $scope.current = {
                'index': i + 1,
                'track': $scope.active.tracks[i + 1]
            };
            $scope.upNext = $scope.active.tracks[i + 2];
            $scope.play($scope.current.track.preview);

            currentIndex++;

            return;
        }

        $scope.closeModal();
    }

I'm sorry if this question might be a tad vague, I can expand if need be.

Edit: The advance() function is called by this function:

$scope.open = function (i, r) {
        console.log(currentIndex);
        $scope.openModal(i, r);

        autoAdvance = window.setInterval(advance, 30000);
    };

Like I say, the advance function works and the $scope variables are being updated; it is just not reflected in the HTML as it updates.

Upvotes: 2

Views: 1046

Answers (1)

bstockwell
bstockwell

Reputation: 514

So, I believe what is occurring is that that the interval isn't passing through angular digest cycle, so it's unaware of the changes to the scope. Whereas, a button click is called from within angular itself, so it's aware of those changes.

Calling $scope.$apply() informs angular of these changes and kickstarts the engine to render the changes. Take the following controller:

function MyCtrl($scope) {
  $scope.name = 'Superhero';

  window.setInterval(function() {
    advance()
  }, 2000);


  function advance() {
    $scope.name += " 1";
  }


  window.setInterval(function() {
    advance2()
  }, 2000);


  function advance2() {
    $scope.name += " 2";
    $scope.$apply()
  }

}

advance1() has no $scope.$apply() call, while the advance2() does. You'll notice that both function calls are reflected in the DOM after the second call.

Here's a fiddle showing the functionality: http://jsfiddle.net/pgxnom55/

Upvotes: 1

Related Questions