Coder Perfect

AngularJS: How can I pass variables between controllers?

Problem

There are two Angular controllers in my application:

function Ctrl1($scope) {
    $scope.prop1 = "First";
}

function Ctrl2($scope) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

Because Ctrl1 is ambiguous, I can’t use it inside Ctrl2. However, if I try to submit it in this manner…

function Ctrl2($scope, Ctrl1) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

I get an error message. Is there anyone who knows how to do it?

Doing

Ctrl2.prototype = new Ctrl1();

Also fails.

These controllers are not nested inside one another.

Asked by dopatraman

Solution #1

Create a service and inject it into any controller where you wish to utilize it to exchange variables across different controllers.

Simple service example:

angular.module('myApp', [])
    .service('sharedProperties', function () {
        var property = 'First';

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function(value) {
                property = value;
            }
        };
    });

In a controller, you may use the service as follows:

function Ctrl2($scope, sharedProperties) {
    $scope.prop2 = "Second";
    $scope.both = sharedProperties.getProperty() + $scope.prop2;
}

This is nicely described in this blog (Lesson 2 and on in particular).

To save the bound reference, I’ve discovered that binding to an object’s property rather than a primitive type (boolean, string, number) works better if you wish to bind to these properties across several controllers.

Instead of var property = ‘First’, use var property = Property1:’First’.

UPDATE: To help (hopefully) clarify things, here’s a fiddle that illustrates an example of:

Answered by Gloopy

Solution #2

I like to use simple examples to convey complex concepts:)

Here’s an example of a simple Service:


angular.module('toDo',[])

.service('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  this.dataObj = _dataObj;
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

Here’s where the jsbin comes in.

Here’s an example of a simple Factory:


angular.module('toDo',[])

.factory('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  return {
    dataObj: _dataObj
  };
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

Here’s where the jsbin comes in.

If that’s too basic, here’s a more advanced example.

For relevant best practices remarks, read the answer here.

Answered by Dmitri Zaitsev

Solution #3

—- I realize this answer isn’t for this question, but I’d like to help anyone who see this question and wish to work with Services like Factories avoid problems ——

You’ll need to use a Service or a Factory for this.

The services are the BEST PRACTICE for sharing data between controllers that are not nested.

How to declare objects is a fantastic commentary on this issue of data exchange. I was unfortunate in that I slipped into an AngularJS trap before learning about it, and I was really frustrated as a result. So allow me to assist you in avoiding this problem.

According to “ng-book: The entire book on AngularJS,” AngularJS ng-models created as bare-data in controllers are WRON.

This is how a $scope element should be created:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // best practice, always use a model
  $scope.someModel = {
    someValue: 'hello computer'
  });

And not in the following way:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // anti-pattern, bare value
  $scope.someBareValue = 'hello computer';
  };
});

This is because it is recommended (BEST PRACTICE) that the calls be contained in the DOM(html document).

<div ng-model="someModel.someValue"></div>  //NOTICE THE DOT.

If you want your child controller to be allowed to change an object from the parent controller, this is especially useful for nested controllers….

You don’t want nested scopes in your situation, but there is a comparable component to getting things from services to controllers.

Let’s imagine your service is called Factory, and the return space comprises an objectA that contains an objectB that contains an objectC.

If you wish to GET the objectC into your scope from your controller, it’s a mistake to say:

$scope.neededObjectInController = Factory.objectA.objectB.objectC;

That’s not going to work… Use only one dot instead.

$scope.neededObjectInController = Factory.ObjectA;

Then you can call objectC from objectA in the DOM. This is a factory best practice that, most importantly, will help to avoid unanticipated and uncatchable faults.

Answered by AFP_555

Solution #4

Using $rootScope instead of establishing a Service:

Angular $rootScope can be used to share properties across app Controllers. Another way to distribute data is to publish it so that others are aware of it.

Services are the ideal approach to share functionality between Controllers, and $rootscope can be used to read or alter a global value.

var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = true;
}]);

app.controller('Ctrl2', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = false;
}]);

Using $rootScope in a template (Accessing $root properties):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>

Answered by Sanjeev

Solution #5

The example above worked perfectly. I simply made a change in case I need to manage numerous variables in the future. I hope this information is useful!

app.service('sharedProperties', function () {

    var hashtable = {};

    return {
        setValue: function (key, value) {
            hashtable[key] = value;
        },
        getValue: function (key) {
            return hashtable[key];
        }
    }
});

Answered by Juan Zamora

Post is based on https://stackoverflow.com/questions/12008908/angularjs-how-can-i-pass-variables-between-controllers