Keith John Hutchison Keith John Hutchison - 3 months ago 11
AngularJS Question

How to call a ngDirective from within an angular controller?

I'm writing an application that plays tracks from soundcloud using angular-soundmanager2. It works but when I play the second track the first track is played again before the second track.

If I manually click the 'Clear Playlist' button created with the following directive before loading the second page this problem is resolved.

<div id="playDiv" ng-show="audioAvailable">
<br/>
<button play-pause-toggle data-play="Play" data-pause="Pause">Play</button>
<button clear-playlist>Clear Playlist</button>
</div>


The code to clear the tracks is created with a directive.

ngSoundManager.directive('clearPlaylist', ['angularPlayer', '$log',
function(angularPlayer, $log) {
return {
restrict: "EA",
link: function(scope, element, attrs) {
element.bind('click', function(event) {
//first stop any playing music
angularPlayer.stop();
angularPlayer.setCurrentTrack(null);
angularPlayer.clearPlaylist(function(data) {
$log.debug('all clear!');
});
});
}
};
}
]);


The code to add the track is essentially.

if ( data.soundcloud_track ) {

SC.stream( '/tracks/' + data.soundcloud_track.id , function( sm_object ){

var track = {
id: data.soundcloud_track.id,
title: data.soundcloud_track.title,
artist: data.soundcloud_track.artist,
url: sm_object.url
};

$rootScope.audioAvailable = true ;

}) ;

}


I have access to globals ngSoundManager, soundManager and angular-soundManager.
Essentially I'd like to clear the playlist first, then add the new track.

How would I call this directive with the angular controller?

Answer

This one it's pretty tricky and can be resolved in many ways (service sharing an object, event on the rootscope..).

I would go this way, personally: first of all, put an isolated scope with a variable on your directive

restrict: "EA",
scope:{
  shareObj: '='
}
link: function(scope, element, attrs) {
  scope.shareObj = angularPlayer.clearPlaylist;
}

and share your function you want to be accessible from external to a variable of the scope.

Then, in your controllerJS:

$scope.shareObj = {};
$scope.clicked = function(){   
   $scope.shareObj(); //you are calling the directive function, ha!
}

and your HTML:

<clear-playlist share-obj="shareObj"> </clear-playlist>

Beware, you must be sure that your link function of the controller has been executed (and thus the function created). If you inject your directive to the dom and immediately need to execute the function, it may not work: in this particular case, wrap your $scope.share() calling in a

$timeout(function(){ 
   $scope.share() 
}, 0);

to be sure a digest cycle has occured.

Comments