2015-02-04 7 views
10

In einer AngularJS-Anwendung (Haupt) habe ich eine iframe innerhalb der es eine andere AngularJS-Anwendung (iframe) auch unter meiner Kontrolle ist. Ich möchte Daten zwischen zwei Diensten teilen, eins in der Hauptanwendung und eins in der iframe Anwendung. Sie müssen beide zum selben Objekt lesen und schreiben.Access AngularJS-Service von einem Service in einem anderen Rahmen

// 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 
} 
// ... 

Wenn in einem Controller in iframe Anwendung verwalten ich serviceA.sharedData wie diese Referenz:

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

dies erreicht werden kann und wie?

Ich habe folgendes gelesen, aber konnte es nicht in eine Lösung drehen, doch:

+0

die Antwort auf die zweite Frage sagt, Sie verweisen, dass Sie das Winkelobjekt eines iframe mit 'theIFrameElement zugreifen können .contentWindow.angular'. Funktioniert das für dich? – user1950929

+0

Ja, es ist möglich, auf das Objekt 'eckig' wie folgt zuzugreifen. Aber wie kann ich dann auf einen darauf registrierten Dienst zugreifen? – hielsnoppe

+0

Sie können den Dienst zu Ihrem Bereich in der Steuerung hinzufügen, dann können Sie von außen darauf zugreifen (d. H. Der Elternrahmen). – user1950929

Antwort

6

Ok, also hier ist meine Lösung, ich hoffe, das ist, was Sie im Sinn hatten.

in der Steuerung der Stammanmeldung:

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

in der Steuerung der iframe Anwendung:

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

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

Die Sachen mit dem iframes funktionieren nicht auf jsfiddle (Quer Ursprung vielleicht) (die js-Datei für den Shared-Service muss nur durch parent.html enthalten sein) so dass ich mein ausführlicheres Beispiel auf eine github Seite:

https://github.com/sammax/angulariframe (Code)

http://sammax.github.io/angulariframe/main/ (Ergebnis)

7

ich es geschafft, etwas zu tun, das funktioniert, und nützlich sein könnte für dich. Es ist nicht perfekt, aber es ist ein guter Anfang. Hier ist der Code:

Geordnete Seite:

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

Kinder Seite:

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

Alle dieser Code führt dazu:

Working code

Der wichtigste Teil ist $scope.data = $window.parent.DataService.getScope(); im Kind-Controller. Dort wird der gemeinsame $ scope abgerufen.

Natürlich funktioniert das alles nur, wenn die Eltern & der Iframe unter der gleichen Domäne sind. Sonst wird es eine ganz andere komplizierte Geschichte ...

Hoffe, das wird dir helfen.

+0

Erstellen Sie ein JFiddle bitte .... –

Verwandte Themen