2013-07-23 5 views
59

Ist es möglich, eine $watch auf einem Array von Objekten innerhalb eines Dienstes einzurichten (Ich möchte die $watch Deklaration selbst im Service sein)?

Antwort

120

Sie können einen beliebigen Ausdruck zum Satz von Uhren hinzufügen, indem Sie die $rootScope und eine Funktion ein erstes Argument in die Methode $watch injizieren. Pseudo-Code:

$rootScope.$watch(function() { 
    return //value to be watched; 
}, function watchCallback(newValue, oldValue) { 
    //react on value change here 
}); 

Vergessen Sie nicht, um die dritte, Boolean Argument an die $watch Methode. Sie müssen true angeben, wenn Sie ein gesamtes Objekt auf Änderungen überwachen möchten.

+0

wenn Sie nichts dagegen haben, ich Sie sho möchten Wie können Sie den Rückgabewert der ersten Funktion referenzieren? Ich habe mein Bestes versucht, aber es ist mir nicht gelungen, auf Veränderungen zu achten.Derselbe Wert wurde ständig und immer wieder zurückgegeben. – Birowsky

+0

@Birowsky Hast du '$ watchCollection' probiert? –

+0

Dies hilft nicht, da es das rootScope für die gesamte Anwendung überwacht. – btm1

15

Dienste von ihrer Natur sind wie Klassen und Hausmethoden. Sie können eine Methode einrichten, die Sie von Ihrem Controller nennen, der das Argument der Umfang ist und wendet eine Uhr Ausdruck:

app.service('myservice',function(){ 
    this.listen = function($scope) { 
     $scope.$watch(function(){return someScopeValue},function(){ 
      //$scope.dosomestuff(); 
     }); 
    } 
}); 

//your controller 

function myCtrl($scope,myservice) { 
    $scope.listen = function() { 
     myservice.listen($scope); 
    } 

    //call your method 
    $scope.listen(); 
} 

Update: Wenn Sie versuchen, einen privaten lokalen Variable innerhalb eines Dienstes zu sehen, finden Sie in der akzeptiert Antwort mit $ rootScope. Wenn Sie versuchen, eine $ scope-Variable innerhalb eines lokalen Bereichs zu beobachten, ist die beste Wette. Sie erreichen zwei sehr unterschiedliche Dinge.

+0

Das mag wie eine dumme Frage erscheinen, aber warum setzen Sie 'myservice.listen ($ scope)' in eine Funktion? Ist es für die einfache Wiederverwendung im gesamten Code oder gibt es einen wichtigen Grund? Außerdem, wenn ich die $ Uhr in eine Fabrik stelle, wird es dann noch funktionieren? –

0

Können Sie klarstellen, was Sie erreichen möchten? Wie ich verstehe, erhalten Sie eine Reihe von Objekten vom Server als Ihr Modell. Dann ist es nicht klar:

  1. Haben Sie, wenn einige Objekte im Array überprüfen möchten haben (vielleicht seit dem letzten Aufruf an den Server im Fall tun Sie rezidivierenden Pooling) geändert?
  2. Möchten Sie überprüfen, ob einige Objekte im Array vom Benutzer über einige Front-End-Steuerelemente geändert wurden?

Im Fall 1, brauchen Sie nicht wirklich $ sehen (oder besser gesagt $ watchCollection) zu verwenden, aber Sie sollten durch das Array, das Sie von dem Server empfangen und überprüfen Sie die Änderungen (das gleiche, was tun würde, $ watchColleciton iterieren). Wenn das Objekt anders ist als das, das Sie gerade halten, rufen Sie das Objekt. $ Save() für dieses Element auf.

Verwenden Sie in Fall 2 $ watchCollection() für den $ scope, der als Parameter für Ihre Servicefunktion übergeben wurde, oder $ rootScope, wenn Sie Ihr Array im $ rootScope halten.

Ich kann Ihnen echten Code zur Verfügung stellen, wenn Sie die Szenarien klären würden.

0

Hey, ich hatte gerade eine Situation, in der ich ein ziemlich großes Uhr-Setup auf 2 verschiedenen Controllern hatte.

Wie ich wollte keinen Code duplizieren ich in meinem Dienst funktioniert nur definiert:

angular 
    .module('invoice') 
    .factory('invoiceState', function() { 
     var invoice = { 
      client_info: { 
       lastname: "", 
       firstname: "", 
       email: "", 
       phone: "", 
       id_client: "", 
       ... 
      } 
     } 
     invoice.watchAccommodation = function (newVal, oldVal) { 
      var accommodation = newVal; 
      //Whatever you would normally have in your watch function 
     } 

Dann

Ich kann in der Uhr jeder Controller diese Funktion nur aufrufen, in die ich den Dienst injiziert
function NewInvoiceCtrl(invoiceState) { 
    $scope.$watch('invoice.accommodation',invoiceState.watchAccommodation, true); 
} 

ich habe nicht viel Erfahrung mit AngularJS so dass ich nicht wirklich in die Leistungsaspekte dieses Ansatzes gehen können, aber es funktioniert;)