AngularJS Modules/Scope Sharing
Asked Answered
A

2

10

I recently started using AngularJS and the way I'm building my apps now is like this:

MainController.js

var app = angular.module('app', ['SomeController', 'MainController']);

app.controller('MainController', function ($scope) {
    // do some stuff
}

SomeController.js

var SomeController= angular.module('SomeController', []);

SomeController.controller('SomeController', function ($scope) {
    $scope.variable = "test";
    // do some otherstuff
}

The problem that Im' running into is that the scope is not being shared between modules. From MainController I can't get the variable "test" for example.

  • What is the best practice for this? Do I store all my controllers in 1 module in 1 file?
  • How can i have 1 page with 2 controllers and share the $scope between them, or is it OK to put everything in just one controller ?
Astronomy answered 23/12, 2013 at 21:5 Comment(3)
This is definitely an X/Y problem. If you need to do something like this, you are doing something majorly wrong. Update your answer to explain what you actually are trying to accomplish.Calque
Basically i'm asking how i should do this, i don't necessarily need to do it like this.Astronomy
See my answer, just be sure that you're packaging things together that belong together and not coupling things that shouldn't be coupled.Calque
C
20

You could use a service like this: Live demo here (click).

JavaScript:

var otherApp = angular.module('otherApp', []);
otherApp.factory('myService', function() {
  var myService = {
    someData: ''
  };
  return myService;
});
otherApp.controller('otherCtrl', function($scope, myService) {
  $scope.shared = myService;
});


var app = angular.module('myApp', ['otherApp']);

app.controller('myCtrl', function($scope, myService) {
  $scope.shared = myService; 
});

Markup:

  <div ng-controller="otherCtrl">
    <input ng-model="shared.someData" placeholder="Type here..">
  </div>
  <div ng-controller="myCtrl">
  {{shared.someData}}
  </div>

Here's a nice article on sharing data with services.

You can also nest controllers to have the parent controller's scope properties inherited by the child scope: http://jsbin.com/AgAYIVE/3/edit

  <div ng-controller="ctrl1">
    <span>ctrl1:</span>
    <input ng-model="foo" placeholder="Type here..">
    <div ng-controller="ctrl2">
      <span>ctrl2:</span>
      {{foo}}
    </div>
  </div>

But, the child won't update the parent - only the parent's properties update the child.

You would use "the dot rule" to have updates on the child affect the parent. That means nesting your properties in an object. Since the parent and child both have the same object, changes on that object will be reflected in both places. That's just how object references work. A lot of people consider it best practice to not use inheritance, but put everything in directives with isolated scope.

Calque answered 23/12, 2013 at 21:19 Comment(7)
Thanks for explaining, is it a common practice to have multiple modules on 1 page/or partial i should say ? i have the idea i'm doing it wrong.Astronomy
@Chancho You're not using multiple modules (and shouldn't be). You're using one module that has a dependency on another module. That sort of coupling is fine, but it seems like you're thinking of it incorrectly. Let's say that Module A is a sort of tool set you've created..maybe it has a service, directory and a controller that work together to provide a nice functionality. Now, you're creating an app, so you make Module B. You decide that Module B could use that functionality you made and packed in Module A, so Module B will have a dependency on Module A.Calque
alright i think i get that now, but what about the controllers that reside in the modules. basically what i'm doing now is create a module with controller inside there. then in another controller i add the module as a dependency to that module. i think this is where i'm going the wrong way. - so to rephrase my question: how do i link multiple controllers with their scope together ?Astronomy
@Chancho In all likeliness, you really want the service solution, like I said. That is linking those scopes together, because they both reference the same object. Otherwise, their's scope inheritance, but it's limited. jsbin.com/AgAYIVE/3/editCalque
If i just want to retrieve a single value from another controller, do i create service for this ?Astronomy
@Chancho Yes. Keep in mind the big picture - a controller isn't meant to care about what is done with data. The controller is just a hub for data to/from the view. With that in mind - the controller's job here is just to associate data from the view with data in the service. Then something else that depends on that service can do something with it. If you get the concept, you should see that there's an issue with whatever is using that data depending on a controller.Calque
best way for your example is to use a service because they are singleton (just an instance) so when you will update $scope.shared.someData (doesnt matter by which controller) the others also will see the update. that is because they have a reference of the same instance object.Posterity
L
0

You can use $rootScope, each Angular application has exactly one root scope.

Reference

app.controller('MainController', function ($scope, $rootScope) {
    $rootScope.data = 'App scope data';
}
Lazos answered 13/8, 2014 at 4:23 Comment(4)
Each module has it's own $rootScope.Cryosurgery
Even if you could access a global like this, and share state -- this is known as "Common Coupling" and its a 'No-No' level 4 out of 5 (Content Coupling being the highest). #badPractice, #tightCoupling, #theBadTypeOfComplexity .Hargis
Mmmm... I'm running Angular 1.5.5 and each module certainly does NOT get it's own $rootScope.Cymar
There is most definitely one $rootScope, or there certainly should be, unless you're doing something wrong like passing it between modules or assigning it to another variable somewhere. I'm not seeing anything in the OP's question that indicates that the variable may not be a static variable (which would be completely appropriate for the $rootScope, and avoids the complexity of a service).Virgilvirgilia

© 2022 - 2024 — McMap. All rights reserved.