5

I'm just getting to grips with Angular, but passing around scope is getting the better of me when I try to abstract reusable components into separate modules.

I'm using an Angular Youtube module found here https://github.com/arnaudbreton/angular-youtube but it's woefully inadequate so I'm bolting on new functionality, namely support for the youtube API's Events.

First, here's the pertinent snippet from the third party module (abridged):

angular.module('youtube', ['ng'])

    .service('youtubePlayerApi', ['$window', '$rootScope', '$log', function ($window, $rootScope, $log) {
        var player = $rootScope.$new(true);

        player.playerContainer = null;

        player.create = function (attrs) {          
            player.playerId = attrs.id;
            player.videoId = attrs.videoId;

            return new YT.Player(this.playerId, {
                videoId: attrs.videoId,

                events:{
                    onStateChange: function(event){
                        switch(event.data){
                            case YT.PlayerState.PLAYING:
                                attrs.onEvent()
                                break;
                        }
                    }
                }
            });
        };

        player.load = function(){
            this.playerContainer = player.create();
        }

        return player;
    }])

    .directive('youtubePlayer', ['youtubePlayerApi', function (youtubePlayerApi) {
        return {
            restrict:'A',
            scope: {
                id:'@',
                videoId:'@',
                onEvent:'&'
            },
            link: function (scope, element, attrs) {
                youtubePlayerApi.create(attrs);
            }
        };
    }]);

Then there's my own module:

var myapp = angular.module('myapp', ['youtube']);

myapp.controller('myAppCtrl', ['$scope', '$rootScope', '$location', '$log', 'youtubePlayerApi', function($scope, $rootScope, $location, $log, youtubePlayerApi) {

    $scope.showVideo = function(){
        $scope.youtubePlayer = youtubePlayerApi.load();
    }

    $scope.myEventHandler = function(){
        alert('finished!')
    }
}]);

and the associated template:

<div ng-app="myapp" id="ng-app">
    <div ng-controller="myAppCtrl">
        <div youtube-player id="ytplayer" video-id="0BWD5I6YrIo" on-event="myEventHandler()"></div>
    </div>
</div>

As you'll see I'm struggling to connect the myeventhandler() function of myAppCtrl with the youtubeapi module.

I'm also not sure I'm configuring the Isolate scope variables correctly as I've only ever seen it done when the scope values are being passed to a template, not a link function like this.

Any pointers on where i'm going wrong?

Dan
  • 59,490
  • 13
  • 101
  • 110
xcession
  • 268
  • 2
  • 11
  • I haven't yet pulled this code into a test app and played with it, but to me it looks like you're doing everything right--the code for the YouTube stuff looks fishy to me. I notice the code on GitHub doesn't match the code here; you may want to try updating the angular-youtube code. – Michelle Tilley Jun 03 '13 at 16:33

1 Answers1

2

The isolate scope variables are configured correctly. attrs.onEvent() does not work because attributes are strings rather than expressions. Still, the directive can pass the event handler to the service using its isolate scope variable:

link: function (scope, element, attrs) {
    // using the isolate scope binding
    youtubePlayerApi.create(attrs, scope.onEvent); 
}

You would then modify create to accept the new parameter:

player.create = function (attrs, handler) {

And also within create, change attrs.onEvent() to handler()

Dan
  • 59,490
  • 13
  • 101
  • 110
  • Thanks guys, I had a suspicion I was almost there, it was all down to passing scope fo the handler. – xcession Jun 04 '13 at 11:15