12

I have to implement some standard notification UI with angular js. My approach is the following (simplified):

<div ng-controller="MainCtrl">
  <div>{{message}}</div>
  <div ng-controller="PageCtrl">
     <div ng-click="showMessage()"></div>
  </div>
</div>

And with the page controller being:

module.controller("PageCtrl", function($scope){
  counter = 1
  $scope.showMessage = function(){
    $scope.$parent.message = "new message #" + counter++;
  };
});

This works fine. But I really don't like the fact that I need to call $scope.$parent.

Because if I am in another nested controller, I will have $scope.$parent.$parent, and this becomes quickly a nightmare to understand.

Is there another way to create this kind of global UI notification with angular?

standup75
  • 4,734
  • 6
  • 28
  • 49
  • 3
    try creating a service that would hold your messages, and inject the service to both controllers. just google for 'communicating controllers angularjs' it will show tons of links. – akonsu Jun 18 '13 at 15:55

5 Answers5

17

Use events to send messages from one component to another. That way the components don't need to be related at all.

Send an event from one component:

app.controller('DivCtrl', function($scope, $rootScope) {
  $scope.doSend = function(){
    $rootScope.$broadcast('divButton:clicked', 'hello world via event');
  }
});

and create a listener anywhere you like, e.g. in another component:

app.controller('MainCtrl', function($scope, $rootScope) {
  $scope.$on('divButton:clicked', function(event, message){
    alert(message);
  })
});

I've created a working example for you at http://plnkr.co/edit/ywnwWXQtkKOCYNeMf0FJ?p=preview

You can also check the AngularJS docs about scopes to read more about the actual syntax.

This provides you with a clean and fast solution in just a few lines of code.

Regards, Jurgen

jvandemo
  • 13,046
  • 2
  • 23
  • 18
7

You should check this: An AngularJS component for easily creating notifications. Can also use HTML5 notifications. https://github.com/phxdatasec/angular-notifications

Victor Landau
  • 71
  • 1
  • 4
  • 1
    That project seems to be abandoned. Someone else has taken over maintenance and merged several PRs at: https://github.com/phxdatasec/angular-notifications. See announcement at: https://github.com/DerekRies/angular-notifications/issues/13 – Joseph S. Jul 21 '14 at 13:54
3

After looking at this: What's the correct way to communicate between controllers in AngularJS? and then that: https://gist.github.com/floatingmonkey/3384419

I decided to use pubsub, here is my implementation:

Coffeescript:

module.factory "PubSub", ->
  cache = {}
  subscribe = (topic, callback) ->
    cache[topic] = [] unless cache[topic]
    cache[topic].push callback
    [ topic, callback ]
  unsubscribe = (topic, callback) ->
    if cache[topic]
      callbackCount = cache[topic].length
      while callbackCount--
        if cache[topic][callbackCount] is callback
          cache[topic].splice callbackCount, 1
    null
  publish = (topic) ->
    event = cache[topic]
    if event and event.length>0
      callbackCount = event.length
      while callbackCount--
        if event[callbackCount]
          res = event[callbackCount].apply {}, Array.prototype.slice.call(arguments, 1)
      # some pubsub enhancement: we can get notified when everything
      # has been published by registering to topic+"_done"
      publish topic+"_done"
      res

  subscribe: subscribe
  unsubscribe: unsubscribe
  publish: publish

Javascript:

module.factory("PubSub", function() {
  var cache, publish, subscribe, unsubscribe;
  cache = {};
  subscribe = function(topic, callback) {
    if (!cache[topic]) {
      cache[topic] = [];
    }
    cache[topic].push(callback);
    return [topic, callback];
  };
  unsubscribe = function(topic, callback) {
    var callbackCount;
    if (cache[topic]) {
      callbackCount = cache[topic].length;
      while (callbackCount--) {
        if (cache[topic][callbackCount] === callback) {
          cache[topic].splice(callbackCount, 1);
        }
      }
    }
    return null;
  };
  publish = function(topic) {
    var callbackCount, event, res;
    event = cache[topic];
    if (event && event.length > 0) {
      callbackCount = event.length;
      while (callbackCount--) {
        if (event[callbackCount]) {
          res = event[callbackCount].apply({}, Array.prototype.slice.call(arguments, 1));
        }
      }
      publish(topic + "_done");
      return res;
    }
  };
  return {
    subscribe: subscribe,
    unsubscribe: unsubscribe,
    publish: publish
  };
});
Community
  • 1
  • 1
standup75
  • 4,734
  • 6
  • 28
  • 49
1

My suggestion is don't create a one on your own. Use existing models like toastr or something like below. http://beletsky.net/ng-notifications-bar/

Madura Pradeep
  • 2,378
  • 1
  • 30
  • 34
0

As suggested above, try to use external notifications library. There're a big variety of them: