10

I have controller A which sends some data to shared service and controller B which should read that data. The problem is Controller B is on a different page (on same website) than controller A, i.e. I do smth. on controller A, click button (which sends data to service) and open another page where is controller B which should read data from service. But nothing happens, so my question is can controllers on different pages communicate this way ?

Here is how I tried to do it but with no luck:

Service:

publicApp.angularModule.service('controllerCommunicationService', function ($rootScope) {
    var communicationService = {};
    communicationService.data = null;

    communicationService.setDataForBroadcast = function(data) {
        this.data = data;
        this.broadcastData();
    };

    communicationService.broadcastData = function() {
        $rootScope.$broadcast('handleBroadcast');
    };

    return communicationService;
});

Relevant parts of controller A:

publicApp.angularModule.controller('PublicRoutinesCtrl', function ($scope, $rootScope, routinesService, controllerCommunicationService, bootstrapCarouselService) {


    $scope.goToNextScreen = function() {
        var currentIndex = bootstrapCarouselService.getcurrentSlideIndex();
        controllerCommunicationService.setDataForBroadcast($scope.items[currentIndex].Routine.RoutineId);



    };

Relevant parts of controller B:

 $rootScope.$on('handleBroadcast', function () {
        console.log("TEST");
        $http.post("/EditWorkout/PostRoutineId", { routineId: controllerCommunicationService.data })
             .success(function() {
                 console.log("success");
             })
            .error(function (responseData) {
            console.log("Error !" + responseData);
        });
    });

And even console.log("TEST"); isn't fired.

hyperN
  • 2,674
  • 9
  • 54
  • 92

4 Answers4

7

based on your question

my question is can controllers on different pages communicate this way ?

The answer is no. Angular and javascript for that matter are not designed like that.

If however you mean different views on the same page, then yes, you can use a service. Services are singletons and keep their data across controllers when kept on the same page.

If you really want to send data from one page to another your options are to do it via a querystring(on the url) or posting the data, or if you are supporting only modern browsers then you can use the client side local storage (http://www.w3schools.com/html/html5_webstorage.asp)

Anton
  • 7,709
  • 5
  • 31
  • 33
  • More of an FYI than a solution, but if you put 'controllerCommunicationService.setDataForBroadcast()' in a $timeout with a sufficient delay, your code will work provided the target page has enough time to load. Definitely not reliable though. – Lavamantis Oct 16 '13 at 21:54
5

Well there are also two other ways to communicate between tabs. Via cookies with global domain, which is not recommended as not secure.

Or with postMessage:

https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage?redirectlocale=en-US

Demo:

http://html5demos.com/postmessage2

And browser support:

http://caniuse.com/#feat=x-doc-messaging

Sebastian Piskorski
  • 4,026
  • 3
  • 23
  • 29
3

I assume when you jump between tabs, you are unfortunately reloading the entire page - Do not do that. Instead use routeProvider to setup a nice routing.

var App = angular.module('App', []);
App.config(function($routeProvider) {
  $routeProvider.when('/tab1', {templateUrl: 'views/tab1.html'});
  $routeProvider.when('/tab2', {templateUrl: 'views/tab2.html'});
  $routeProvider.otherwise({redirectTo: '/tab1'});
});

Then the rest of your code would work and retain the shared data stored by the service even when you switch tabs. In case, you do not want to use the $routeProvider then write a logic in your service to persist the data using localStorage, indexDB, etc.

As far as I can see,you are using Angular controllers and services then it should not be a problem using $routes too. :-)

codef0rmer
  • 10,284
  • 9
  • 53
  • 76
1

$rootScope.$broadcast is a perfectly acceptable way to communicate between controller, but since you are using across page it would not work. This is because when your do the broadcast call the other controller is not loaded and hence it's on method does not get fired. But since your service has a property data you can directly access it by injecting the service into the other controller and access it's data property

controllerCommunicationService.data anytime and anywhere you want so no need for using on method.

As explained by @Anton you can also pass data using querystring\url fragements and client storage.

Chandermani
  • 42,589
  • 12
  • 85
  • 88