Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
54
rated 0 times [  59] [ 5]  / answers: 1 / hits: 36975  / 12 Years ago, wed, october 17, 2012, 12:00:00

AngularJS noob here, on my path to the Angular Enlightenment :)



Here's the situation:



I have implemented a service 'AudioPlayer' inside my module 'app' and registered like so:



 app.service('AudioPlayer', function($rootScope) {

// ...

this.next = function () {
// loads the next track in the playlist
this.loadTrack(playlist[++playIndex]);
};

this.loadTrack = function(track) {
// ... loads the track and plays it
// broadcast 'trackLoaded' event when done
$rootScope.$broadcast('trackLoaded', track);
};
}


and here's the 'receiver' controller (mostly for UI / presentation logic)



app.controller('PlayerCtrl', function PlayerCtrl($scope, AudioPlayer) {


// AudioPlayer broadcasts the event when the track is loaded

$scope.$on('trackLoaded', function(event, track) {
// assign the loaded track as the 'current'
$scope.current = track;
});

$scope.next = function() {
AudioPlayer.next();
};
}


in my views I show the current track info like so:



<div ng-controller=PlayerCtrl>
<button ng-click=next()></button>
// ...
<p id=info>{{current.title}} by {{current.author}}</p>
</div>


the next() method is defined in the PlayerCtrl, and it simply invokes the same method on the AudioPlayer service.



The problem



This works fine when there is a manual interaction (ie when I click on the next() button) - the flow is the following:




  1. PlayerCtrl intercepts the click and fires its own next() method

  2. which in turn fires the AudioPlayer.next() method

  3. which seeks the next track in the playlist and calls the loadTrack() method

  4. loadTrack() $broadcasts the 'trackLoaded' event (sending out the track itself with it)

  5. the PlayerCtrl listens the broadcast event and assigns the track to the current object

  6. the view updates correctly, showing the current.title and current.author info



However, when the next() method is called from within the AudioService in the 'background' (ie, when the track is over), all the steps from 1 to 5 do happen, but the view doesn't get notified of the change in the PlayerCtrl's 'current' object.



I can see clearly the new track object being assigned in the PlayerCtrl, but it's as if the view doesn't get notified of the change. I'm a noob, and I'm not sure if this is of any help, but what I've tried is adding a $watch expression in the PlayerCtrl



$scope.$watch('current', function(newVal, oldVal) {
console.log('Current changed');
})


which gets printed out only during the 'manual' interactions...



Again, like I said, if I add a console.log(current) in the $on listener like so:



$scope.$on('trackLoaded', function(event, track) {
$scope.current = track;
console.log($scope.current);
});


this gets printed correctly at all times.



What am I doing wrong?



(ps I'm using AudioJS for the HTML5 audio player but I don't think this is the one to blame here...)


More From » angularjs

 Answers
96

When you have a click event the $scope is updated, without the event you'll need to use $apply



$scope.$apply(function () {
$scope.current = track;
});

[#82511] Monday, October 15, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
freddiem

Total Points: 456
Total Questions: 116
Total Answers: 101

Location: Dominica
Member since Mon, Jan 4, 2021
3 Years ago
;