2013-05-23 13 views
31

Buduję witrynę e-commerce (w oparciu o shopify) i używam wielu małych aplikacji angularjs do obsługi takich rzeczy jak szybki koszyk na zakupy, listy życzeń, filtrowanie produktów i kilka innych mniejszych przedmiotów. Początkowo używałem jednej dużej aplikacji (która miała routing i wszystko), ale było trochę restrykcyjne, gdy nie miałem pełnego API REST.Udostępnianie pojedynczej usługi między wieloma aplikacjami angular.js

Jest kilka usług, które chciałbym udostępnić między aplikacjami kątowymi (usługa koszyka, dzięki czemu mogę mieć przycisk szybkiego dodawania, który będzie odzwierciedlał w mini-wózku itp.), Ale nie jestem na pewno najlepszy sposób (jeśli istnieje sposób), aby to osiągnąć. Po prostu udostępnienie modułu z usługą nie zachowuje tego samego stanu w aplikacjach.

Próbowałem na to ręką, ale nie wydaje mi się, aby zaktualizować stan między obu aplikacji. Poniżej znajduje się javascript, którego próbowałem użyć. Jest to także na jsfiddle z html towarzyszących: http://jsfiddle.net/k9KM7/1/

angular.module('test-service', []) 
    .service('TestService', function($window){ 
    var text = 'Initial state'; 

    if (!!$window.sharedService){ 
     return $window.sharedService; 
    } 

    $window.sharedService = { 
     change: function(newText){ 
     text = newText; 
     }, 
     get: function(){ 
     return text; 
     } 
    } 

    return $window.sharedService; 
    }); 

angular.module('app1', ['test-service']) 
    .controller('App1Ctrl', function($scope, TestService){ 
    $scope.text = function(){ return TestService.get() } 
    $scope.change = function(){ TestService.change('app 1 activated') } 
    }); 

angular.module('app2', ['test-service']) 
    .controller('App2Ctrl', function($scope, TestService){ 
    $scope.text = function(){ return TestService.get() } 
    $scope.change = function(){ TestService.change('app 2 activated') } 
    }); 

var app1El = document.getElementById('app1'); 
var app2El = document.getElementById('app2'); 

angular.bootstrap(app1El, ['app1', 'test-service']); 
angular.bootstrap(app2El, ['app2', 'test-service']); 

Każda pomoc będzie mile widziane

Odpowiedz

24

The sharedService jest wspólną, ale jeden kątowy aplikacja nie wiedzieć, że coś jest aktualizowane w innej aplikacji, więc nie robi” t rozpoczyna się od $digest. Trzeba ręcznie powiedzieć $rootScope każdej aplikacji, aby rozpocząć $digest wywołując $rootscope.$apply()

Fiddle: http://jsfiddle.net/pvtpenguin/k9KM7/3/

angular.module('test-service', []) 
    .service('TestService', function($rootScope, $window){ 
    var text = 'Initial state'; 
    $window.rootScopes = $window.rootScopes || []; 
    $window.rootScopes.push($rootScope); 

    if (!!$window.sharedService){ 
     return $window.sharedService; 
    } 

    $window.sharedService = { 
     change: function(newText){ 
     text = newText; 
     angular.forEach($window.rootScopes, function(scope) { 
      if(!scope.$$phase) { 
       scope.$apply(); 
      } 
     }); 
     }, 
     get: function(){ 
     return text; 
     } 
    } 

    return $window.sharedService; 
    }); 
+0

który działa ładnie. W jaki sposób zaproponowałbym, aby zrobić coś $ window.rootScopes z wieloma usługami współdzielonymi? Zakładam, że podwoiłoby się, gdybym nie był ostrożny. –

+0

Ach, nie martw się, wymyśliłem dobry sposób na zrobienie tego - umieść go w bloku uruchamiania w aplikacjach, a nie w udostępnionych modułach. –

+0

@ TomBrunoli możesz rozwinąć o tym, co zrobiłeś? W jaki sposób przeniesiono kod usługi z udostępnionych modułów do bloku uruchamiania aplikacji bez błędów? – kevin11

3

starałem się rozwiązać podobny problem. Udostępnianie fabryk między aplikacjami działającymi w różnych ramach iFrame. Chciałem, aby każdy $apply() w dowolnej ramce powodował cykl trawienia we wszystkich innych ramkach. Zezwalanie na proste ng-clicks wiąże się bezpośrednio z metodą fabryczną, aby zaktualizować widok we wszystkich innych ramkach. I stworzył moduł, który obsługuje wiązania zakresów i dzielenie fabryk:

Click here to see plunkr

Wystarczy zawierać moduł o każdej aplikacji:

angular.module('App', ['iFrameBind']) 

I zmienić oświadczenie żadnego fabryki RETURN, aby powrócić do wersji udostępnionej tej fabryki:

return sharedFactory.register('counter', service); 

np.

.factory('counter', function (sharedFactory) { 

    var service; 
    var val = 0; 

    function inc() { 
    val++; 
    } 

    function dec() { 
    val--; 
    } 

    function value() { 
    return val; 
    } 

    service = { 
    inc: inc, 
    dec: dec, 
    value: value 
    }; 

    return sharedFactory.register('counter', service); 
}) 

.directive('counter', function (counter) { 
    return { 
    template: '{{counter.value()}} ' + 
       '<button ng-click="counter.inc()">Up</button> ' + 
       '<button ng-click="counter.dec()">Down</button> ', 
    restrict: 'E', 
    link: function postLink(scope) { 
     scope.counter = counter; 
    } 
    }; 
}); 

aktualizacje licznik w obu ramkach gdy kliknięcie dzieje w obu

Powiązane problemy