4

I've multiple controllers in my application, where I have some duplicate code like:

$scope.alert = null;

$scope.addAlert = function (message) {
    $scope.alert = { type: 'danger', msg: message };
};

$scope.clearAlerts = function () {
    $scope.alert = null;
};

What is the recommended way sharing these scope functions and variables in AngularJS? Using controller inheritance?

6
  • Using services docs.angularjs.org/guide/services Commented Mar 23, 2015 at 14:18
  • possible duplicate of Global variables in AngularJS Commented Mar 23, 2015 at 14:18
  • Controller inheritance is not a good practice. Use factory and service for that Commented Mar 23, 2015 at 14:19
  • possible duplicate of AngularJS - single alert div for multiple controllers Commented Mar 23, 2015 at 14:27
  • 1
    In my case I created an alert service that receives from the controllers the type, title and message, and presents the alert to the user based on that information. the answer from @pankajparkar seems to be the way to go. The service will only be accessible to the controllers you inject the dependency in.... Commented Mar 25, 2015 at 17:43

2 Answers 2

5

Create a one controller and then place common methods inside that controller scope. So that you can use that scope anywhere else and get access to method inside controller.

Controller

app.controller('commonCtrl', function($scope) {
    $scope.alert = null;

    $scope.addAlert = function(message) {
        $scope.alert = {
            type: 'danger',
            msg: message
        };
    };

    $scope.clearAlerts = function() {
        $scope.alert = null;
    };
});

Thereafter use scope of this controller by inject it using $controller, and then inside curly brace you could assign common controller scope to the current scope of controller.

Utilization of Common Controller

app.controller('testCtrl', function($scope, $controller) {
    //inject comomon controller scope to current scope , 
    //below line will add 'commonCtrl' scope to current scope
    $controller('commonCtrl', { $scope: $scope }); 
    //common controller scope will be available from here

});

Or more precise way would be using common sharable service, that exposed two method and alert data, you can use this service method by injecting service name inside your controller.

Service

app.service('commonService', function($scope) {
    this.alert = null;

    this.addAlert = function(message) {
        this.alert = {
            type: 'danger',
            msg: message
        };
    };

    this.clearAlerts = function() {
        this.alert = null;
    };
});

Utilization of service inside Controller

app.controller('testCtrl', function($scope, commonService) {

  console.log(commonService.alert);
  commonService.addAlert("Something");
  console.log("Updated Alert" + commonService.alert);

});

Hope this has cleared your concept, Thanks.

Sign up to request clarification or add additional context in comments.

3 Comments

You should use a service not a controller
How can I add a service in AngularJS 1.3+? It seems that it's done using a factory, but then all my controllers will share the alert. I need each controller using my service, to have it own instance.
@DennisMadsen If your requirement is like such, then do create a new controller would be better way (as I mentioned in 1st approach)..rather than creating a service which will initialized new object & give new copy of variable, service/factory does mean that you should use them for shareable purpose
0

My own solution for this use case was to define a type of Observer Pattern.

The code was structured in the following way:

var app = angular.module('testModule', []);
app.factory('alertService', ['$timeout', function($timeout){
    var alertListeners = [];

    this.register = function (listener) {
        alertListeners.push(listener);
    };

    this.notifyAll = function (data) {
    for (// each listener in array) {
        var listenerObject = alertListeners[i];
        try { // do not allow exceptions in individual listeners to corrupt other listener processing
            listenerObject.notify(data);
        } catch(e) {
            console.log(e);
        }   
    }
    };
 }]).
 directive('myAlerts', ['alertService', function(alertService){

     var alertDirectiveObserver = function($scope, alertService) {

        this.notify = function(data) {
        /*
         * TO DO - use data to show alert
         */
         };

         /*
          * Register this object as an event Listener. Possibly supply an event key, and listener id to enable more resuse
          */
         alertService.register(this);

         $scope.on('$destroy', function() {
             alertService.unregister(// some listener id);
         });
     };


   return {
     restrict: 'A',
     template: '<div ng-class="alertClass" ng-show="alertNeeded">{{alertMessage}}</div>',
     controller: ['$scope', 'alertService', alertDirectiveObserver],
     link: function(scope){  
     }
    }
}]).
controller('alertShowingController', ['$scope', 'alertService',   function($scope, alertService){
    alertService.notifyAll({'warning', 'Warning alert!!!'})   
 ]);

The alertShowingController is a simple example of how all controllers can simply inject the alertService and generate an event.

My own implementation is more elaborate in that it uses separate event keys to allow the controllers to generate other event notifications.

I could then define a single div that was in a fixed position at the top of the page that would dispay bootstrap alerts.

<div my-alerts ng-repeat="alert in alertList" type="{{alert.type}}" close="closeAlert(alertList, $index)">{{alert.msg}}</div>

2 Comments

In your example it seems that alerts are shared between all controllers, right? I need each controller to have it's own alert.
I created a plunker plnkr.co/edit/BRFAGyeEN29SESVzLPPJ?p=preview, which may help for what you are trying to do

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.