使用AngularJS服务从其他模块更新其他控制器中的范围

时间:2015-11-02 15:45:59

标签: angularjs angularjs-service angularjs-controller

我是AngularJS的新手,所以也许我正在以错误的方式看待这个。如果是这样,请指出我正确的方向。

基本上我想更新一些位于另一个模块中另一个控制器的DOM元素。 我正在尝试通过服务发送数据,但似乎它没有在目标范围上更新。

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!!
}]);

我希望在initialize()中调用appCtrl函数时,它会看到服务中的currentID参数,mainCtrl也使用该参数。

2 个答案:

答案 0 :(得分:2)

为了使用服务更新控制器,我强烈建议您使用$rootScope.$broadcast$rootScope.$on。以下是如何执行此操作并链接到博客的示例:

$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/

这是您的工作解决方案:

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();
    }


});

和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>

答案 1 :(得分:0)

你有几种不同的方法可以做到这一点。

我同意uksz,您应该使用broadcast / emit让其他范围知道更改,让他们根据需要处理。

广播转到元素的所有子范围

$(document).on('submit', '#soundOffForm', function(event){
    event.preventDefault();
    $.ajax({
        type: "POST",
        url: "sessionsetter.php",
        data: {
            sound : '0',
        },
        success: function(data) {
            //alert("Sound toggled successfully: " + data);
            $('#soundToggle').load(location.href + " #soundOnForm");

        },
        error: function(data) {
            alert("Error in processing request: " + data);
        }
    });
});

$(document).on('submit', '#soundOnForm', function(event){
    event.preventDefault();
    $.ajax({
        type: "POST",
        url: "sessionsetter.php",
        data: {
            sound : '1',
        },
        success: function(data) {
            //alert("Sound toggled successfully: " + data);
            $('#soundToggle').load(location.href + " #soundOffForm");
        },
        error: function(data) {
            alert("Error in processing request: " + data);

        }
    });
});

Emit将转到此元素的所有父作用域

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

其他选项是您还可以要求其他控制器

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

最后,您可以在范围中包含一个功能,这样您就可以让父范围了解正在进行的操作

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