AngularJS: Communication between directives

前端 未结 4 762
时光说笑
时光说笑 2021-01-01 05:33

I\'m writing a directive which creates an mp3/audio player. The issue is that you can have many audio players in one page. What I would like to do is when one is playing and

相关标签:
4条回答
  • 2021-01-01 06:08

    Make a service that each directive uses and hold the state in there.

    Something like this:

    angular.module('MyPlayer' [])
    .factory('playerState', function() {
        var players = [];
        return {
            registerPlayer: function(player) {
                players.add(player);
            },
            unregisterPlayer: function(player) {
                var i = players.indexOf(player);
                (i>-1) && players.splice(i,1);
            },
            stopAllPlayers: function() {
                for(var i=0;i<players.length;i++) {
                    players[i].stop();
                }
            }
        }
    })
    
    .directive('player', function(playerState) {
        return {
            ...
            link: function(scope, elem, attr) {
                var player = {
                    stop: function() {
                        /* logic to stop playing */
                    },
                    play = function(song) {
                        playerState.stopAllPlayers();
                        /* logic to start playing */
                    }
                }
    
                playerState.registerPlayer(player);
                scope.$on("$destroy", function() {
                    playerState.unregister(player);
                });
    
                scope.play = player.play;
                scope.stop = player.stop;
    
                ...
            }
        }
    })
    
    0 讨论(0)
  • 2021-01-01 06:17

    You can also do $rootScope.$broadcast events like playerStarted. This event can be subscribed by all directives and they can react to this event by stopping themselves. The one thing that you need to do would be pass in the data about the player which is starting so that the new player does not stop itself as it too would subscribe to such event.

    0 讨论(0)
  • 2021-01-01 06:23

    Just to make the answers complete, next to broadcasting events, and exposing a service, you can also use directive controllers. These controllers are set through the controller property of a directive definition object and are shared between directives that require the same controller. This means you can have one controller for all the media players, where you can implement the logic you mentioned. See the documentation on directives (search for controller:) for more information.

    I would recommend the service approach if you think there will be more consumers of the logic, or the directive controller approach if only the directives consume the logic. I would advise against broadcasting events on the root scope because of the uncoupled and global nature of it. Just my two cents! HTH

    0 讨论(0)
  • 2021-01-01 06:27

    How are your directives setup? Please provide some code.

    This depends on the scope of your directives, I'm going to assume a child scope. To communicate between the directives, when a user clicked to start a player, I would call a $scope.$parent.$broadcast() - or $rootScope.$broadcast() if the directives are in different controllers or using isolated scopes, but then you need to inject $rootScope into your directive - to send an event to all child scopes. My directives would be watching for this event using $on and any players that were playing would stop. After this broadcast the player clicked would start.

    $broadcast() and $on() scope documentation

    0 讨论(0)
提交回复
热议问题