2

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.

4
  • Did you move the code from inside of a controller to a new advance function outside of the controller? The scope of the $scope variable is going to be separate in that case. Commented May 11, 2016 at 15:55
  • No, the advance function is in the same controller and I know the $scope is updating correctly, just the HTML template isn't picking it up Commented May 11, 2016 at 15:56
  • 1
    Ok, It might help to see some more of your code, especially the places where you're calling advance()--for both the click and the interval. Commented May 11, 2016 at 15:57
  • Please see the edits Commented May 11, 2016 at 16:00

1 Answer 1

1

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/

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

1 Comment

Thank you! This is exactly what I was looking for, I could tell there was a step missing that the button was able to rectify. Works great.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.