2015-02-04 14 views
10

W aplikacji AngularJS (główna) mam iframe, wewnątrz której znajduje się również inna aplikacja AngularJS (iframe) również pod moją kontrolą. Chciałbym udostępnić dane między dwiema usługami, jedną w głównej aplikacji i jedną w aplikacji iframe. Oboje muszą czytać i pisać do tego samego obiektu.Dostęp do usługi AngularJS z usługi wewnątrz innej ramki

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

Kiedy wewnątrz kontrolera w aplikacji iframe udało mi się odwoływać serviceA.sharedData takiego:

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

Można to osiągnąć iw jaki sposób?

Czytałem następujące, ale nie mógł przekształcić go w roztworze jeszcze:

+0

odpowiedź na drugie pytanie ty odwołanie twierdzi, że można uzyskać dostęp do kątową obiektu iframe z 'theIFrameElement .contentWindow.angular'. Czy to Ci pasuje? – user1950929

+0

Tak, możliwe jest uzyskanie dostępu do obiektu 'kątowego' w ten sposób. Ale w jaki sposób mogę uzyskać dostęp do zarejestrowanej usługi? – hielsnoppe

+0

możesz dodać usługę do swojego zakresu w kontrolerze, a następnie uzyskać do niej dostęp z zewnątrz (tj. Ramkę nadrzędną). – user1950929

Odpowiedz

6

Ok, więc oto moje rozwiązanie, mam nadzieję, że właśnie o tym myślałeś.

w sterowniku stosowania macierzystego:

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

w sterowniku stosowania 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 (plik js dla udostępnionej usługi, musi być zawarte tylko przez 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 } 
    } 
}); 

Rzeczy z iframe nie działa na jsfiddle (Cross pochodzenia może) tak kładę na przykład szerszą strona GitHub:

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

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

7

udało mi się zrobić coś, co działa, a może być użyteczne dla Ciebie. Nie jest idealny, ale jest dobrym początkiem. Oto kod:

strona nadrzędna:

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

strona dziecka:

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

Wszystko tego kodu prowadzi do tego:

Working code

Ważną częścią jest $scope.data = $window.parent.DataService.getScope(); w kontrolerze dziecięcej. W tym miejscu pobiera wspólny zakres $.

Oczywiście wszystko działa tylko wtedy, gdy element nadrzędny & znajduje się w tej samej domenie. Innym, staje się cała inna skomplikowana historia ...

Mam nadzieję, że to ci pomoże.

+0

Utwórz jsfiddle please .... –

Powiązane problemy