2015-05-02 12 views
5

Ho un servizio definito come qualcosa di simile a questo:Angolare: Watch Service per le modifiche dei dati?

appServices.service('SharedData', function() { 
    var data = {}; 

    function setContacts(contacts) { 
     data.contacts = contacts; 
    }; 

    function getContacts() { 
     return data.contacts; 
    }; 

    return { 
     setContacts: setContacts, 
     getContacts: getContacts 
    }; 
}); 

In un altro controllore, ho accedere ai dati nel modo seguente:

$scope.contacts = SharedData.getContacts(); 

Questo è tutto bene - ma mi piacerebbe $scope.contacts essere avvisati e aggiornare i suoi dati ogni volta che cambiano i dati in SharedData.

Come posso realizzare questo?

+1

è possibile utilizzare un evento ... –

risposta

2

Un modo per farlo sarebbe definire una funzione nel servizio che consente di registrare una richiamata da chiamare quando viene chiamato setContacts (onContactsUpdated di seguito). Questa soluzione non è perfetta (ad esempio, ti consente solo di registrare un singolo "gestore"), ma dovrebbe portarti sulla giusta strada. Potresti modificarlo se deve essere usato in più posti.

appServices.service('SharedData', function() { 
    var data = {}; 

    function setContacts(contacts) { 
     data.contacts = contacts; 
     if(typeof(data.contactsUpdatedCallback) !== "undefined"){ 
      data.contactsUpdatedCallback(); 
     } 
    }; 

    function getContacts() { 
     return data.contacts; 
    }; 

    function onContactsUpdated(callback){ 
     data.contactsUpdatedCallback = callback; 
    }; 

    return { 
     setContacts: setContacts, 
     getContacts: getContacts, 
     onContactsUpdated: onContactsUpdated 
    }; 
}); 

Poi nel controller:

SharedData.onContactsUpdated(function(){ 
    //do something with updated SharedData.getContacts() 
}); 
3

provare un orologio esplicito:

$scope.$watch(function() { return SharedData.getContacts(); }, function(newContacts) { // Do something with newContacts. });

Se gli elementi della collezione possono cambiare senza l'intera identità oggetto di raccolta che cambia (presumo uno Array o Object), sarà necessario utilizzare $scope.$watchCollection, anche se è notevolmente più lento t han plain $watch, quindi evita di modificare l'intera collezione in una sola volta.

Nota che potrebbe essere il design più bello per esporre una funzione per la portata che restituisce semplicemente i contatti in corso:

$scope.getContacts = function() { return SharedData.getContacts(); };

Se avete bisogno di notifica entro SharedData, si può iniettare $rootScope in esso e mettere il $watch su quello.

+0

Con l'avviso che un semplice orologio non si attiverà se un singolo contatto è stato aggiornato. È necessario utilizzare '$ scope. $ WatchCollection' se si è interessati anche a questo. – floribon

+0

@floribon Non mi interessa usare '$ watch' in questo modo - l'esecuzione di un tale metodo su ogni ciclo di digest sembra errata. Tuttavia, il modo in cui il servizio è scritto, un semplice '$ watch' funzionerà perché l'intera raccolta viene sempre rimessa ogni volta con' setContacts'. Spero sarete d'accordo che '$ watchCollection' è un modo molto doloroso per andare, in quanto potenzialmente itera attraverso ogni bambino in cerca di cambiamenti. http://jsperf.com/angularjs-watchcollection-on-large-dataset –

+0

Bello! Sono nuovo di Angular e ho scritto la mia risposta senza saperlo. –

3

diffidare di abusarne, ma questo è proprio il genere di cosa che $rootScope è per:

appServices.service('SharedData', function($rootScope) { 
    var data = {}; 
    function setContacts(contacts) { 
    data.contacts = contacts; 
    $rootScope.$broadcast('contacts-changed', contacts); 
    }; 
    ... 

Ora, in qualsiasi ambito si desidera, è possibile iscriversi a questo evento:

function($scope) { 
    $scope.$on('contacts-changed', function(eventObj) {...}); 
} 
+0

Grazie di cuore. Il passato in var 'nv' ha un significato particolare? – Jibran

+0

Ha! Hai preso un errore Io uso 'nv' per rappresentare" nuovo valore ", ma in questo caso, è meglio chiamare qualcosa come" evt', ed è l'oggetto evento: https://docs.angularjs.org/api/ng/type/$ rootScope.Scope –

+0

Questo ha più senso, grazie. Un'altra domanda: quale sarebbe considerato l'abuso di questa tecnica? Lo userò per trasmettere una dozzina o più eventi "modificati". – Jibran

Problemi correlati