Wesman80
Wesman80

Reputation: 67

Using AngularJS service to update scope in other controller from other module

I am a newbie for AngularJS so maybe I am looking at this the wrong way. If so, please point me in the right direction.

Basically I want to update some DOM elements that reside in another controller in another module. I am trying to send data through a service but it seems that it is not updated on the destination scope.

var mainModule = angular.module('main', []);
var appModule = angular.module('app', ['main']);


appModule.controller("appCtrl", function ($scope, $routeParams, mainService) {

    $scope.mainService = mainService;

    var initialize = function () {
        $scope.mainService.currentID = $routeParams.productId;
    }

    initialize();
});


mainModule.factory('mainService', function () {
    var mainService = { currentID: 0 };
    return mainService
});

mainModule.controller('mainCtrl', ['$scope', 'mainService', function ($scope, mainService) {

    $scope.mainService = mainService;
    $scope.function1Url = "function1/" + $scope.mainService.currentID;
    $scope.function2Url = "function2/" + $scope.mainService.currentID;
    //CurrentID is always 0!!
}]);

I expect that when calling the initialize() function in the appCtrl, it will see the currentID param in the service which is also used by the mainCtrl.

Upvotes: 1

Views: 1294

Answers (2)

Vince
Vince

Reputation: 787

You have a couple different methods of doing this.

I agree with uksz, you should use broadcast/emit to let other scopes know of the change, let them handle as needed.

Broadcast goes to all child scopes of the element

$scope.$broadcast("Message Name", "payload, this can be an object"); 

Emit goes to all parent scopes of this element

$scope.$emit("message name", "payload, this can be an object"); 

Other option is you can also require the other controller

appModule.directive('myPane', function() {
  return {
    require: '^myTabs',
    scope: {},
    link: function(scope, element, attrs, tabsCtrl) {
      tabsCtrl.addPane(scope);
    }
  };
});

Lastly you can include a function on the scope so you can let the parent scope know what's going on

appModule.directive('myPane', function() {
  return {
    scope: {
      doSomething: '&something'
    },
    link: function(scope, element, attrs) {
      $scope.doSomething(test);
    }
  };
});

Upvotes: 0

uksz
uksz

Reputation: 18699

For updating controller using service, I strongly recommend you to use $rootScope.$broadcast and $rootScope.$on. Here is an example of how you can do it, and link to a blog:

$rootScope.$broadcast('myCustomEvent', {
  someProp: 'Sending you an Object!' // send whatever you want
});

// listen for the event in the relevant $scope
$rootScope.$on('myCustomEvent', function (event, data) {
  console.log(data); // 'Data to send'
});

http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Here is your working solution:

var mainModule = angular.module('main', []);
var productModule = angular.module('product', ['main']);

productModule.service('mainService', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
    this.method1 = function () {
      alert('broadcast');
           $rootScope.$broadcast('myCustomEvent', {
                newValue: 'This is an updated value!' 
            });
    }
}]);

productModule.controller('mainCtrl', ['$scope', '$rootScope', function ($scope, $rootScope){

    $scope.myValue = 'Initial value';

     $rootScope.$on('myCustomEvent', function (event, data) {
        $scope.myValue = data.newValue;
        alert('received broadcast');
    });

}]);

productModule.controller("productCtrl", function ($scope, mainService) {

    $scope.mainService = mainService;
    $scope.clickMe = 'Click to send broadcast';

    $scope.callService = function () {
      $scope.clickMe = 'Broadcast send!';
       $scope.mainService.method1();
    }


});

And HTML:

  <body ng-app='main'>
    <div  ng-controller="mainCtrl"><b>My value:</b>{{myValue}}</div>

    <div  id="product" ng-controller="productCtrl">
      <button ng-click="callService()">{{clickMe}}</button>
    </div>

    <script type="text/javascript">angular.bootstrap(document.getElementById("product"), ['product']);</script>
  </body>

Upvotes: 2

Related Questions