How to listen for a site-wide event in a directive

2019-07-04 15:55发布

I am creating a custom chart widget in angularjs using a directive with isolated scope. The idea being that each widget should be able to exist in isolation after receive basic config information on how to create itself.

The widget will communicate with other parts of the application by listening for an "update.data" event. When the event is triggered, the widget knows to refresh its data (Make a call to the server) based on new config information available to it, passed through the event object.

A sample widget created is as below

 ng.directive('metricOverview', ['Report', function(Report) {
        return {
            restrict: 'EA',
            //replace: true,
            scope: {
                title: '@',
                metrics: '=',
                report: '@'
            },
            templateUrl: 'scripts/widgets/metric-overview/metric-overview.html',
            controller: function($scope, $element)
            {
            },
            link: function(scope, element, attrs) {
                scope.$on("update.data", function()
                {
                    Report.overview({metric: scope.metric, report: scope.report})
                            .$promise.then(function(result) {
                                console.log(result);

                                $(document).trigger("chart.refresh", result);

                            });
                });

            }
        };
    }]);

My question is where is it most appropriate to trigger the "update.data" event. For example, when the page is loaded and the DOM is ready, I want this event to be triggered and all loaded widgets should be able to listen for it and update themselves. I cannot trigger the event on the rootScope since it isnt accessible within the directive's isolate scope.

Done a couple of research but bulk of what I found relied on the use of a global/parent scope which doesnt serve my purpose due to the isolated nature of the directives

What will be the best way to approach this?

1条回答
够拽才男人
2楼-- · 2019-07-04 16:28

Hi handle this scenario with an eventbus service that uses the rootscope and $emit so the event does not go down lots of child scopes. You could just inject this service into the directive and added an event listener.

(function (angular) {
'use strict';

/**
 * @ngdoc service
 * @name coreModule.eventbus
 * @requires $rootScope
 *
 * @description
 * Provides a eventing mechanism when a user cna broadcast and subscribe to application wide events.
 */
angular.module('coreModule').factory('eventbus', [
    '$rootScope',
    function ($rootScope) {
        /**
         * @ngdoc function
         * @name subscribe
         * @methodOf coreModule.eventbus
         *
         * @description
         * Subscribes a callback to the given application wide event
         *
         * @param {String} eventName The name of the event to subscribe to.
         * @param {Function} callback A callback which is fire when the event is raised.
         * @return {Function} A function tht can be called to unsubscrive to the event.
         */
        var subscribe = function (eventName, callback) {
                return $rootScope.$on(eventName, callback);
            },

            /**
             * @ngdoc function
             * @name broadcast
             * @methodOf coreModule.eventbus
             *
             * @description
             * Broadcasts the given event and data.
             *
             * @param {String} eventName The name of the event to broadcast.
             * @param {object} data A data object that will be passed along with the event.
             */
            broadcast = function (eventName, data) {
                $rootScope.$emit(eventName, data);
            };

        return {
            subscribe: subscribe,
            broadcast: broadcast
        };
    }
]);
}(angular));
查看更多
登录 后发表回答