0

I want to know how to correctly use the $emit method correctly so that inside my error callback I can fire a modal.

I have the following factory:

angular.module('BBPlnkr').factory("Session", [
  '$http', '$q', '$rootScope', function($http, $q, $rootScope) {
    var service;
    service = {
      requestCurrentUser: function() {
        if (service.isAuthenticated()) {
          return $q.when(service.currentUser);
        } else {

        }
        return $http.get('current_user').then(function(resp) {
          console.log(resp.data);
          service.currentUser = resp.data;
          return service.currentUser;
        }, function(resp) {
          if (resp.status === 401) {
            $rootScope.$emit("loginRequired", "err");
            console.log('You are not authetnicated');
          }
        });
      },
      currentUser: null,
      isAuthenticated: function() {
        return !!service.currentUser;
      }
    };
    return service;
  }
]);

What this factory simply does is just checks if the user is the current_user and if not it returns a 401. What I'd like to do is inside that error callback is fire a modal when this error callback is called. Now I was found out I could use the $emit method but am not sure if I am using it correctly. Inside the error callback I want to dispatch the event up through the scope chain. Which is what $emit does right. But I am not entirely sure if I set this up correctly. So in doing this. I have my controller like so:

myApp.controller('MainController', ['$scope', '$rootScope', '$modal', '$location', '$route', function($scope, $rootScope, $modal, $location, $route) {

      $rootScope.$on('loginRequired', function(event, second_param){
        /* Do the modal stuff here??*/
    });
  }
]);

I am aware I am not actually doing anything to fire trigger a modal ($modal.open). BUT I wanted to know if I heading in the right direction. If not, some advice would be helpful. I have looked online for documentation around $emit, $broadcast. I know the difference between the two. Once dispatches events up the scope chain and one dispatches events down the $scope chain.

user532339
  • 179
  • 9

2 Answers2

1

option 1

angular.module('BBPlnkr').factory("Session", [
  '$http', '$q', '$rootScope','$scope', function($http, $q, $rootScope,$scope) {
    var service;
    service = {
      requestCurrentUser: function() {
        if (service.isAuthenticated()) {
          return $q.when(service.currentUser);
        } else {

        }
        return $http.get('current_user').then(function(resp) {
          console.log(resp.data);
          service.currentUser = resp.data;
          return service.currentUser;
        }, function(resp) {
          if (resp.status === 401) {
            $scope.$emit("loginRequired", "err");
            console.log('You are not authetnicated');
          }
        });
      },
      currentUser: null,
      isAuthenticated: function() {
        return !!service.currentUser;
      }
    };
    return service;
  }
]);

option2

myApp.controller('MainController', ['$scope', '$rootScope', '$modal', '$location', '$route', function($scope, $rootScope, $modal, $location, $route) {
$rootScope.loginRequired = fn(){}

  }
]);

angular.module('BBPlnkr').factory("Session", [
  '$http', '$q', '$rootScope', function($http, $q, $rootScope) {
    var service;
    service = {
      requestCurrentUser: function() {
        if (service.isAuthenticated()) {
          return $q.when(service.currentUser);
        } else {

        }
        return $http.get('current_user').then(function(resp) {
          console.log(resp.data);
          service.currentUser = resp.data;
          return service.currentUser;
        }, function(resp) {
          if (resp.status === 401) {
            $rootScope.loginRequired()
            console.log('You are not authetnicated');
          }
        });
      },
      currentUser: null,
      isAuthenticated: function() {
        return !!service.currentUser;
      }
    };
    return service;
  }
]);

But I think you are overusing root scope and the scope of emit and broadcast

  1. Emit and broadcast are used to communicate across scopes, here you are using to communicate in the same scope. $rootScope is only one for entire app. it is kind of global cache.
  2. Since rootScope is global and unique across application, you should use it sparingly. I would go for option1, in that only the top level module is accessing rootScope that too only to listen to what children scopes are doing.

Reference : http://docs.angularjs.org/api/ng/type/$rootScope.Scope

himangshuj
  • 730
  • 5
  • 9
  • Thank you for the detailed explanation. However... with option 1. I am certain you cannot access `$scope` on a factory level. Furthermore having looked at: http://stackoverflow.com/a/19498009/3189939 he states advises: to use $rootScope.$emit+ $rootScope.$on also the use of `$emit` Dispatches an event name upwards through the scope hierarchy notifying the registered. So would it not be wise to use `$emit` rather than `$broadcast` – user532339 Feb 26 '14 at 09:59
  • The initial suggestion of using `$broadcast` works. And in my controller I do `$scope.on('loginRequired, function(){ console.log 'something happened });` which works – user532339 Feb 26 '14 at 10:28
0

Himangshuj mentions some good points about scope above, so I won't chime in on that.

If you're looking for a clean way to handle dialogs from within your controller, this thread has a directive that could be used with Bootstrap or similar modal dialog frameworks.

Simple Angular Directive for Bootstrap Modal

With the directive and your dialog markup, showing the modal should be as easy as $scope.showDialog = true; from within your controller.

Hope that helps.

Community
  • 1
  • 1
Ender2050
  • 6,912
  • 12
  • 51
  • 55