【问题标题】:Access AngularJS service from a service inside a different frame从不同框架内的服务访问 AngularJS 服务
【发布时间】:2015-02-04 10:09:13
【问题描述】:

在一个 AngularJS 应用程序(主)中,我有一个 iframe,其中还有另一个 AngularJS 应用程序(iframe)也在我的控制之下。我想在两个服务之间共享数据,一个在主应用程序中,一个在 iframe 应用程序中。它们都需要读取和写入同一个对象。

// main
// ... routes ...
views: { main: {
  controller: function ($scope, serviceA) {
    $scope.serviceA = serviceA;
  },
  templateUrl: 'iframe.html'
}
// ...
function ServiceA () {
  this.sharedData; // exposed to controllers in main app
}
// ...

// iframe
// ...
function ServiceB () {
  this.sharedData; // exposed to controllers in iframe app
}
// ...

在 iframe 应用程序的控制器内部时,我设法像这样引用 serviceA.sharedData

var self = this;
var parentScope = $window.parent.angular.element($window.frameElement).scope();
parentScope.$watch('serviceA.sharedData', function (newValue, oldValue) {
  self.sharedData = newValue;
}

这可以实现吗?如何实现?

我已阅读以下内容,但仍无法将其转化为解决方案:

【问题讨论】:

  • 您引用的第二个问题的答案是,您可以使用theIFrameElement.contentWindow.angular 访问 iframe 的角度对象。这对你有用吗?
  • 是的,可以像这样访问angular 对象。但是我如何才能访问在其上注册的服务呢?
  • 您可以将服务添加到控制器中的范围,然后您可以从外部(即父框架)访问它。

标签: javascript angularjs iframe


【解决方案1】:

我设法做了一些有效的事情,并且可能对你有用。这并不完美,但却是一个好的开始。代码如下:

父页面:

<div ng-controller="ParentController">
    <h1>Hello, parent page!</h1>

    <p><strong>Parent model:</strong></p>
    <p>
        <input type="text"
           ng-model="data.foo"
           placeholder="Enter the thing you want to share"/>
    </p>

    <p><strong>Parent result:</strong></p>
    <p>{{ data.foo }}</p>

    <iframe src="child-page.html" frameborder="0"></iframe>
</div>

子页面:

<div ng-controller="ChildController">
    <h1>Hello, child page!</h1>

    <p><strong>Child result:</strong></p>
    <p>{{ data.foo }}</p>
</div>

app.js

var app = ng.module('myApp', []);

app.factory('DataService', ['$rootScope', '$window', function ($rootScope, $window) {
    var // Variables
        dataScope,

        // Functions
        getScope;

    dataScope = $rootScope.$new(true);

    getScope = function () {
        return dataScope;
    };

    $window.DataService = {
        getScope: getScope
    };

    return {
        getScope: getScope
    };
}]);

app.controller('ParentController', ['$scope', 'DataService', function ($scope, DataService) {
    $scope.data = DataService.getScope();
}]);

app.controller('ChildController', ['$scope', '$window', '$interval', function (
    $scope,
    $window,
    $interval
) {
    $scope.data = $window.parent.DataService.getScope();

    // makes a $scope.$apply() every 500ms. Without it, data doesn't change
    $interval(ng.noop, 500);
}]);

所有这些代码都会导致:

重要的部分是子控制器中的$scope.data = $window.parent.DataService.getScope();。这就是它获取共享 $scope 的地方。

当然,所有这些都只有在父级和 iframe 位于同一域下时才有效。否则,它就变成了另一个复杂的故事......

希望这会对你有所帮助。

【讨论】:

    【解决方案2】:

    好的,这就是我的解决方案,我希望这是你的想法。

    在父应用的控制器中:

    mainApp = angular.module('mainApp', []);
    mainApp.controller('mainCtrl', ['$scope', 'sharedData', function($scope, sharedData){
        $scope.sharedData = sharedData;
        //your controller logic goes here ...
    }]);
    

    在 iframe 应用程序的控制器中:

    iframeApp = angular.module('iframeApp', []);
    iframeApp.controller('iFrameCtrl', function($scope){
        //here we get the service instance from the parent application, if you 
        //need it in other controllers in the iframe app as well, either get it 
        //there the same way or pass it along via $scope or $rootScope
        var sharedData = window.parent.angular.element(window.frameElement).scope().sharedData;
        //now we can use sharedData the same way as in the parent application controller
    

    });

    sharedData.js(共享服务的js文件,只需parent.html包含)

    mainApp.factory('sharedData', function(){
        var list = [];
        var mainScope;
        var iframeScope;
    
        //this function needs to be called in all setter methods to update the data in both applications
        function update(){
            if(!mainScope){
                mainScope = angular.element(document.body).scope();
            }
            //$apply() causes errors in the dev console, $applyAsync doesn't, I don't know why
            mainScope.$applyAsync(); 
            if(!iframeScope){
                //the update function might be called before angular is initialized in the iframe application
                if(document.getElementById('iframe').contentWindow.angular){
                    iframeScope = document.getElementById('iframe').contentWindow.angular.element(document.body).scope();
                    iframeScope.$applyAsync();
                }
            } else {
                iframeScope.$applyAsync();
            }
        }
        return {
            append: function(item) {
                list.push(item); 
                //don't forget to add this at the end of all setter functions in the service
                update();
            },
            getAll: function() { return list }
        }
    });
    

    带有 iframe 的东西在 jsfiddle 上不起作用(可能是跨域),所以我将更广泛的示例放在 github 页面上:

    https://github.com/sammax/angulariframe(代码)

    http://sammax.github.io/angulariframe/main/(结果)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-17
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多