Explanation
There is not really any built in support for cross-app communication in AngularJS, so it can be a bit tricky. But it is possible.
First it's important to understand the difference between module, app and instances.
In this case we will use the word app to describe the entire composition of modules.
In your case you have:
- app1 - which consists of the module
app1.
- app2 - which consists of the modules
app2 and app1.
Now when you use either ng-app or angular.bootstrap to bootstrap an application a new instance of the app is created.
Each instance gets its own instance of the $injector service.
Now comes an important part - each service in AngularJS is a singleton in the sense that it is only created once per $injector instance (including $rootScope).
This means that after you have bootstrapped the both applications you will have:
Instance of app1 -> Instance of $injector -> Instance of service
Instance of app2 -> Instance of $injector -> Instance of service
So there are two instances of service, each with their own internal state. Which is why the data is not shared in your case.
So it wouldn't even matter if you instead bootstrapped app1 two times, there would still be two instances of everything.
How to
To retrieve an app´s injector instance you can use the injector method that is available on angular elements.
Note that this is not the same as the method angular.injector, which is used to create entire new instances of $injector.
Retrieve a reference to a DOM element of a specific app that was used with ng-app or angular.bootstrap:
var domElement = document.getElementById('app1');
Turn it into an angular (jqLite) element:
var angularElement = angular.element(domElement);
Retrieve the app's injector:
var injector = angularElement.injector();
Use the injector to retrieve the correct instance of a service:
var myService = injector.get('myService')
Call the service:
myService.doSomething();
If this is done outside of Angular's digest loop you will need to trigger it manually:
var rootScope = injector.get('$rootScope');
rootScope.$apply();
Or:
var scope = angularElement.scope();
scope.$apply();
Example solution
We have two apps:
var app1 = angular.module('app1', ['shared']);
var app2 = angular.module('app2', ['shared']);
app1.controller('MyController', function($scope, sharedFactory) {
$scope.sharedFactory = sharedFactory;
});
app2.controller('MyController', function($scope, sharedFactory) {
$scope.sharedFactory = sharedFactory;
})
Both apps use the shared module consisting of a factory named sharedFactory with the following api:
var api = {
value: 0,
increment: increment,
incrementSync: incrementSync
};
Remember that each app has its own instance of the factory.
The increment method will simply increment the value. If called from app1 the incrementation will take place in app1's instance of the service.
The incrementSync method will increment the value in both app1's and app2's service instance:
function incrementSync() {
var app1InjectorInstance = angular.element(document.getElementById('app1')).injector();
var app2InjectorInstance = angular.element(document.getElementById('app2')).injector();
console.log(app1InjectorInstance === app2InjectorInstance); // false
var app1SharedFactoryInstance = app1InjectorInstance.get('sharedFactory');
var app2SharedFactoryInstance = app2InjectorInstance.get('sharedFactory');
console.log('app1-sharedFactory:', app1SharedFactoryInstance);
console.log('app2-sharedFactory:', app2SharedFactoryInstance);
app1SharedFactoryInstance.increment();
app2SharedFactoryInstance.increment();
var otherInjectorInstance = app1SharedFactoryInstance === api
? app2InjectorInstance
: app1InjectorInstance;
otherInjectorInstance.get('$rootScope').$apply();
}
Note that if incrementSync is for example called from within app1, we will be in app1's digest loop, but we will have to start app2´s digest loop manually. This is what the part involving otherInjectorInstance does.
Demo: http://plnkr.co/edit/q2ZEG8VqxHORRzLy8wqZ?p=preview
Hopefully this will help you get going and find a solution to your problem.
newor names used by the framework, for exampleservice. It is a very bad practice and can lead to nasty debugging problems.app2. There is no error there. The issue should be with the controller scope. Add this line:$scope.data = service.data;inctrl2after$scope.scope2and before$scope.update2. In your HTML add this line<p>{{data.list.name}}</p>after the button "run from app2". Then you can see that the controller works fine and the service is called.app1andapp2. So you can share the scope between the controllers.