2014-12-14 3 views
3

Итак, я хочу создать директиву, которая выводит глобальное сообщение.Создание системы сообщений «App-Wide» в Angular

Требования директивы ...

  1. Эта директива сообщения может обновляться с любого контроллера.

  2. Когда сообщение обновляется с любого контроллера, таким образом, это директива, следовательно, вид.

  3. Очистить сообщение после того, как точка зрения destoryed

До сих пор я делаю это путем создания директивы и обслуживания, которые работают вместе. Проблема: я не могу обновить представление, когда сообщение обновляется из других контроллеров.

Если кто-то может направить меня на то, как действовать, что будет набухать. Как насчет использования $ 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

Я думаю, что ваша идея $ rootScope и вещания звучит нормально. – Kolban

+0

Я думал, что было бы проще и чище использовать $ rootScope, но я не уверен, как это сделать. Смогу ли я использовать директиву, но не услугу? – JerryA

ответ

1

Используйте $ rootscope. $ Испускают для отправки сообщений от контроллеров (и даже услуги), а также использование $ rootScope. $ На их получение в вашей директиве.

Вы должны удалить слушателя при уничтожении объекта директивы или у вас будет утечка памяти.

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 пустым строковым сообщением.

Это не распространяется на динамическое добавление или удаление директивы в DOM. Для этого вы можете использовать сервис для добавления, а затем удалить тег директивы. Вот как работают модули, такие как модульные службы ngToast и ui.boostrap. Использование одного из них может быть более подходящим для того, что вы хотите выполнить.

+0

Я сделал точно так же, как вы предоставили, но пока не появится сообщение, и у меня нет ошибок в консоли. Позвольте мне посмотреть, смогу ли я это понять. – JerryA

+1

Действительно ли HTTP-вызов успешно возвращается к исходу? Есть ли директива предупреждения уже существует на странице или вы хотите добавить ее динамически, когда есть предупреждение для показа? Если вы хотите динамически отображать предупреждение, как всплывающее сообщение, которое вы хотите использовать для тоста. [link] (http://tameraydin.github.io/ngToast/) - это способ сделать это. – meticoeus

+0

Да, я попробовал директиву по моему основному макету и шаблонам. Кроме того, я испугался из нескольких мест. Console.log() не выполняется внутри функции ссылки. Можете ли вы использовать emit в корневой области для запуска часов в корневой области? – JerryA