在Angular中创建“App-Wide”消息系统

时间:2014-12-14 23:23:15

标签: angularjs angularjs-directive

所以我想创建一个输出全局消息的指令。

指令要求......

  1. 可以从任何控制器更新此指令消息。

  2. 当从任何控制器更新消息时,指令就是视图。

  3. 在视图被破坏后清除消息

  4. 到目前为止,我通过创建一个协同工作的指令和服务来实现这一目标。 问题是当从其他控制器内部更新消息时,我无法更新视图

    如果有人可以指示我如何继续这将会膨胀。 使用$ rootScope和广播怎么样?

    app.directive("alertMsg", ['MsgService', function(MsgService) {
            return {
                restrict: "E",
                scope: true,
                template: '{{msg}}', // this string is the html that will be placed inside the <alert-msg></alert-msg> tags.
                link: function (scope, $element, attrs) {
                    scope.msg = MsgService.getAlertMsg(); //set msg to be available to the template above <alert-msg>{{msg}}</alert-msg>
                    scope.$on("$destroy", function(){ //when the <alert-msg> view is destroyed clear the alert message
                        MsgService.clearAlertMsg();
                    });
                }
            };
        }]);    
    
    
    app.service('MsgService', function() {  
                    this.alertMsg = '';
                    this.getAlertMsg = function(){
                        return this.alertMsg;
                    };
                    this.setAlertMsg = function(string) {
                        this.alertMsg = string;
                    };
                    this.clearAlertMsg = function(){
                        this.alertMsg = '';
                    };
                });
    
    
    app.controller('NewPlateController', ['urlConfig', '$scope', '$http', '$location', 'MsgService', '$routeParams', function(urlConfig, $scope, $http, $location, MsgService, $routeParams) {
            $scope.plate = {license_plate: $routeParams.plate, state: 'default-state'};
            // create new plate via json request
            $scope.createPlate = function(){
                $http.post(urlConfig.rootUrl+"/plates.js", $scope.plate).success(function(data) { 
                    $scope.plateInfo = data;
                    MsgService.setAlertMsg('Plate Sucessfully Created'); //Need to update the directive to actual show this update
                    $location.path('/plate/'+$scope.plateInfo.plate_id);
                // http error: display error messages
                }).error(function(data,status,headers,config) {
                    $scope.errors = data;
                    $('#new-plate-errors').slideDown('fast');
                });
            };
        }]);
    

1 个答案:

答案 0 :(得分:1)

使用$ rootscope。$ emit从您的控制器(甚至服务)发送消息,并使用$ rootScope。$ on在您的指令中接收它们。

您必须删除指令范围销毁时的侦听器,否则您将发生内存泄漏。

app.directive("alertMsg", ['$rootScope', function($rootScope) {
    return {
        restrict: "E",
        scope: true,
        template: '{{msg}}', // this string is the html that will be placed inside the <alert-msg></alert-msg> tags.
        link: function (scope, $element, attrs) {
            var _unregister; // store a reference to the message event listener so it can be destroyed.

            _unregister = $rootScope.$on('message-event', function (event, message) {
                scope.msg = message; // message can be value, an object, or an accessor function; whatever meets your needs.
            });

            scope.$on("$destroy", _unregister) //when the <alert-msg> view is destroyed remove the $rootScope event listener.
        }
    };
}]);

app.controller('NewPlateController', ['urlConfig', '$scope', '$http', '$location', '$rootScope', '$routeParams', function(urlConfig, $scope, $http, $location, $rootScope, $routeParams) {
    $scope.plate = {license_plate: $routeParams.plate, state: 'default-state'};
    // create new plate via json request
    $scope.createPlate = function(){
        $http.post(urlConfig.rootUrl+"/plates.js", $scope.plate).success(function(data) { 
            $scope.plateInfo = data;
            $rootScope.$emit('message-event', 'Plate Sucessfully Created'); //use $emit, not $broadcast. Only $rootscope listeners are called.

            scope.$on("$destroy", function() { // remove the message when the view is destroyed.
                $rootScope.$emit('message-event', "");
            });

            $location.path('/plate/'+$scope.plateInfo.plate_id);
        // http error: display error messages
        }).error(function(data,status,headers,config) {
            $scope.errors = data;
            $('#new-plate-errors').slideDown('fast');
        });
    };
}]);

该消息不会在指令之外持久化,因此当其范围被销毁时将被删除。

编辑:添加一个显示工作示例的JSFiddle:http://jsfiddle.net/kadm3zah/

编辑2:我错过了删除删除视图被删除时添加的消息的要求。使用此方法,您可以使用空字符串消息向NewPlateController范围内的消息添加第二个emit。

这不包括向DOM动态添加或删除指令。为此,您可以使用服务添加并稍后删除指令标记。这就是模块与ngToast和ui.boostrap的模态服务一样的工作方式。使用其中一个可能更适合您想要完成的任务。