2013-05-23 13 views
31

Sto costruendo un sito di e-commerce (basato su shopify) e sto usando più piccole applicazioni angularjs per gestire cose come un carrello della spesa veloce, liste dei desideri, prodotti di filtraggio e un pochi altri oggetti più piccoli. Inizialmente ho usato una grande applicazione (che aveva routing e tutto), ma era un po 'restrittiva quando non avevo un'API REST completa.Condividi un singolo servizio tra più app angular.js

Ci sono un paio di servizi che vorrei condividere tra le app angolari (il servizio di carrello, quindi posso avere un pulsante di aggiunta rapida che si rifletterà nel mini-carrello e così via), ma io non sono sicuro del modo migliore (se c'è un modo) per andare su questo. La semplice condivisione di un modulo con il servizio non mantiene lo stesso stato in tutte le app.

Ci ho provato, ma non mi sembra di aggiornare lo stato tra le due app. Quello che segue è il javascript che ho provato ad usare. E 'anche sulla jsfiddle con html accompagnamento: 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']); 

Qualsiasi aiuto sarebbe apprezzato

risposta

24

Il sharedService è condiviso, ma un app angolare non sa che qualcosa aggiornato in altra applicazione in modo che doesn' t dare il via a $digest. Devi dire manualmente il $rootScope di ogni applicazione di avviare un $digest chiamando $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

che funziona bene. Come vorresti proporre che io faccia la cosa $ window.rootScopes con più servizi condivisi? Presumo che si raddoppierebbe se non fossi attento –

+0

Ah non preoccuparti, ho trovato un buon modo per farlo - mettilo in un blocco di esecuzione nelle app, non i moduli condivisi –

+0

@TomBrunoli puoi elaborare su cosa hai fatto? Come hai spostato il codice di servizio dai moduli condivisi al blocco di esecuzione delle app senza errori? – kevin11

3

stavo cercando di risolvere un problema simile. Condivisione di fabbriche tra app in esecuzione in diversi iFrame. Volevo qualsiasi $apply() in qualsiasi frame per causare un ciclo di digest in tutti gli altri frame. Consentendo il semplice ng-clicks associato direttamente a un metodo factory per aggiornare la vista in tutti gli altri frame. Ho creato un modulo che gestisce il legame di scopi e condivisione delle fabbriche:

Click here to see plunkr

Proprio includono il modulo su ogni app:

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

e cambiare istruzione return qualsiasi fabbrica per restituire la versione condivisa di quella fabbrica:

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

ad es.

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

aggiornamenti contatore in entrambi i telai quando scatto avviene in entrambe le

Problemi correlati