2

So I have figured out how to make the directive and controller communicate and it populates the embed code properly. I don't get any errors in the console and the html looks identical to the manually created embed. But the flash created by the directive doesn't function at all. Any thoughts or ideas as to why this is would be awesome.

This is what the site looks like

Here is the code:

index.html

    <!DOCTYPE html>
    <html>
    <head>
        <link rel="stylesheet" href="dist/css/bootstrap.css"/>
        <link rel="stylesheet" href="dist/css/bootstrap-theme.css"/>
    </head>

    <body ng-app="App">
    <div ng-controller="MainCtrl">
        <div class="col-md-12">
            <h2>This is from the Controller and Directive</h2>
            Song[0] ID: {{Song[0].$id}}
            <flash-widget id="Song"></flash-widget>
        </div>
    </div>
    <div class="col-md-12">
        <h2>This is done Manually</h2>
        Song[0] ID: 4453334
        <object width="250" height="40">
            <embed src="http://grooveshark.com/songWidget.swf" type="application/x-shockwave-flash" width="250"height="40"flashvars="hostname=cowbell.grooveshark.com&amp;songIDs=4453334&amp;style=metal&amp;p=0" allowscriptaccess="always" wmode="window"/>
        </object>
    </div>
    </body>

    <script src="dist/js/angular.js"></script>
    <script src="js/tester.js"></script>
    </body>
    </html>

tester.js

    angular.module("App", [])
        .controller("MainCtrl", function($scope) {
            $scope.Song=[{
                    "AlbumName":"Unknown Album",
                    "ArtistName":"Angel City",
                    "SongName":"Love Me Right Feat. Laura McAllen[Rezonance Q Remix]",
                    "$id":"4453334",
                    "$priority":null
                },
                    {
                        "AlbumName":"Immersion",
                        "ArtistName":"Pendulum",
                        "SongName":"The Island - Part 1 - Dawn",
                        "$id":"26593443",
                        "$priority":null
                    },
                    {
                        "AlbumName":"Someone to Love Me",
                        "ArtistName":"Jomanda",
                        "SongName":"Got a Love for You",
                        "$id":"29376555",
                        "$priority":null
                    },
                    {
                        "AlbumName":"Avicii - Essential Mix (2010-12-11)",
                        "ArtistName":"Avicii",
                        "SongName":"Penguin",
                        "$id":"29533653",
                        "$priority":null
                    },
                    {
                        "AlbumName":"MOS Addicted To Bass 2011",
                        "ArtistName":"Eric Prydz",
                        "SongName":"Niton (The Reason)",
                        "$id":"30154682",
                        "$priority":null
                    }]
        })
        .directive('flashWidget', function(){
            return{
                restrict: 'E',
                scope: {id: '='},
                template: '<object width="250" height="40">'+
                '<embed src="http://grooveshark.com/songWidget.swf" type="application/x-shockwave-flash" width="250" height="40" flashvars="hostname=cowbell.grooveshark.com&songIDs={{id[0].$id}}&style=metal&p=0" allowscriptaccess="always" wmode="window"></embed>'+
                '</object>'
            }
        });

2 Answers 2

2

Here is a plunker for what you are attempting to do: http://plnkr.co/edit/t1UJMLtiBaKQnb7syPJH?p=preview

(function(){


angular.module("App", [])
        .controller("MainCtrl", function($scope) {
            $scope.Song=[{
                    "AlbumName":"Unknown Album",
                    "ArtistName":"Angel City",
                    "SongName":"Love Me Right Feat. Laura McAllen[Rezonance Q Remix]",
                    "$id":"4453334",
                    "$priority":null
                },
                    {
                        "AlbumName":"Immersion",
                        "ArtistName":"Pendulum",
                        "SongName":"The Island - Part 1 - Dawn",
                        "$id":"26593443",
                        "$priority":null
                    },
                    {
                        "AlbumName":"Someone to Love Me",
                        "ArtistName":"Jomanda",
                        "SongName":"Got a Love for You",
                        "$id":"29376555",
                        "$priority":null
                    },
                    {
                        "AlbumName":"Avicii - Essential Mix (2010-12-11)",
                        "ArtistName":"Avicii",
                        "SongName":"Penguin",
                        "$id":"29533653",
                        "$priority":null
                    },
                    {
                        "AlbumName":"MOS Addicted To Bass 2011",
                        "ArtistName":"Eric Prydz",
                        "SongName":"Niton (The Reason)",
                        "$id":"30154682",
                        "$priority":null
                    }];
            $scope.selectedSong = {}; 
            $scope.currentSong = function(){return $scope.selectedSong ; }
            $scope.selectSong = function (i){
                $scope.selectedSong = $scope.Song[i];
            };

        })
        .directive('flashWidget', function(){
            return{
                restrict: 'E',
                scope: {song: '&'},

                link: function(scope, elem, attrs) {

                    function updateDom(song){
                        if (song.$id == undefined)
                            return;
                        elem.html('<object width="250" height="40">'+
                        '<embed src="http://grooveshark.com/songWidget.swf" type="application/x-shockwave-flash" width="250" height="40" flashvars="hostname=cowbell.grooveshark.com&songIDs=' +
                        song.$id +
                        '&style=metal&p=0" allowscriptaccess="always" wmode="window"></embed>'+
                    '</object>');

                    }

                    scope.$watch(scope.song, function(value) {
                      updateDom(value)
                    });
                }
            }
        });

})()

Use the '&' operator for establishing a read only linkage between the controller and the directive. The & operator establishes a binding between a directive scope property and an expression in the parent scope. In this instance, the expression in the parent scope is a function that returns current selected song. This current song could have been selected by any means - but in this case, the selection is triggered by a button click event.

Any time the value of this expression changes (in other words when the current selected song changes), the $watch method defined on this directive property is triggered, thus rebinding the DOM element with the new song ID.

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

1 Comment

This is a much more accurate and complete answer. Thank you!
0

The {{id[0].$id}} in your template is not evaluated when the element is added to the page so your flashvars will get an invalid value. Create the element in your link function once you know the value you want to pass to the embed to make sure you're passing the actual value rather than the unevaluated expression.

Something like this:

.directive('flashWidget', function(){
    return{
        restrict: 'E',
        scope: {id: '='},
        link: function(scope, elem) {
            elem.append('<object width="250" height="40">'+
                '<embed src="http://grooveshark.com/songWidget.swf" type="application/x-shockwave-flash" width="250" height="40" flashvars="hostname=cowbell.grooveshark.com&songIDs=' +
                scope.id[0].$id +
                '&style=metal&p=0" allowscriptaccess="always" wmode="window"></embed>'+
            '</object>');
        }
    }
});

Although you'll need to put the creation of the element in a scope.$watch if your data ever changes.

3 Comments

This is also much better than doing templates because it's easier to debug and test your directive. Just add a link attribute to the object you're returning with a function signature of function(scope, element, attrs) and see how scope.id gets populated in your isolate scope.
so does the scope.$watch go in the controller or inside of the link function? also if i have the data change of button click does that need to be put inside the link function also?
The $watch should go in your link function, then in the callback you should remove and recreate the tag if you have a valid value. I'd need more specific details to comment on the button click.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.