Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: share the data of the same controller in two different, not nested parts of the page

Tags:

angularjs

I want to share the data of one controller between two places in my page. For example:

<div ng-app="myApp">
    <div ng-controller="myController">
        <input type="text" ng-model="x" /> {{x}}
    </div>
</div>
<!-- these are in totally different places and I do not want, nor can't nest them -->
<div ng-app="myApp">
    <div ng-controller="myController">
        <input type="text" ng-model="x" /> {{x}}
    </div>
</div>

and of course, this:

var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope) {
    $scope.x = 'test';
});

What can I do so that, no matter what I type first input text will be reflected in the second? And vice versa? Basically the same data being propagated to these two sections, while maintaining a single copy of the data.

JSFiddle here: http://jsfiddle.net/LETAd/

PS: I bootstrap it manually, if this is of any relevance.

Thanks!

like image 862
v_i_m Avatar asked Mar 08 '13 17:03

v_i_m


People also ask

How do you share data between controllers in AngularJS?

Approach: To share data between the controllers in AngularJS we have two main cases: Share data between parent and child: Here, the sharing of data can be done simply by using controller inheritance as the scope of a child controller inherits from the scope of the parent controller.

What is nested controller in AngularJS?

Nested Controllers: AngularJS allows using nested controllers. It means that you have specified a controller in an HTML element which is a child of another HTML element using another controller.

Can we have two controllers in AngularJS?

Angular creates one $scope object for each controller. We also have a $rootScope accessible from every controllers.In case of multiple controllers AngularJS framework creates and pass a different $scope object to each controller so that data and methods of one controller not be accessed in another controller.


2 Answers

To share data between controllers, normally a service is your best option. Put the shared data into the service, and inject the service into the controller:

function myController($scope, MyService) {

Each scope/controller instance will then be able to access the shared data.

Note that services are singletons, so there will only be one instance of your shared data around.

Here is a fiddle (I didn't write it) showing how two controllers can share data.

See also AngularJS: How can I pass variables between controllers? and
Angularjs: two way data bindings and controller reload.

like image 79
Mark Rajcok Avatar answered Oct 11 '22 03:10

Mark Rajcok


Ideally, you should have only one application running in a single page. Since you also need to communicate between the controllers, you should really run a single application. Possibly on body or html. Then you can create a main controller which would encapsulate all your controllers. (controller inheritance).

Here is what it should look like:

<html ng-app="myApp">
  <head>...</head>
  <body ng-controller="MainCtrl">
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div>
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div> 
  </body>

And JS:

function MainCtrl($scope) {
  $scope.mainView = {};
}
function MyCtrl($scope) {

}

We created a mainView object on the MainController, and since MyController and its scope prototypally inherit from MainController we can reach that.
There is one caveat you should be aware of, when you use ngModel, it is almost always best to have a dot in somewhere (paraphrased from angularjs's authors).

Due to javascript's prototypal inheritance:

// In MainCtrl
$scope.mainView.x = "hello";
$scope.myX = "hello";

// In MyCtrl
$scope.mainView.x
>> "hello"
$scope.myX
>> "hello"
$scope.mainView.x = "welcome";
$scope.myX = "welcome";

// In MainCtrl
$scope.mainView.x
>> "welcome"
$scope.myX
>> "hello"

When you ask for a property in an object in javascript, it looks its properties to see if there is one, if not, it goes up in the prototype chain (parent), and looks for it there, it goes up until it finds any or goes at the end of the prototype chain.

So when we set $scope.myX, we don't actually change myX in the parent scope but we create a property called myX in the current scope; because of the hiearchy in the prototype. However, when we set $scope.mainView.x, we first ask for mainView then set x which then results in changing the value in parent scope.

I know it feels kind of unrelated to the original question but surely one would suffer from this when one goes into controller and scope inheritance.

like image 43
Umur Kontacı Avatar answered Oct 11 '22 04:10

Umur Kontacı