2013-11-27 7 views
17

Ich versuche, this SO answer explaining how to render a recursive JSON structure using a directive zu folgen. Im Gegensatz zu der angegebenen Antwort sind meine Daten jedoch nicht bekannt, wenn das DOM geladen wird und Angular zum ersten Mal ausgeführt wird.Aktualisierung der Angular JS-Anweisung, wenn sich der Dienst ändert

Stattdessen werden meine Daten aus einem HTML-Eingabefeld abgerufen und in einem Angular Service gespeichert (wenn der Benutzer das Formular abschickt).

Wie kann ich eine Winkelrichtlinie auf dem neuesten Stand halten, wenn die Daten des Dienstes geändert werden?


-Update in Reaktion

zu beantworten @musically_ut eine ausgezeichnete Antwort zur Verfügung gestellt, die dazu beigetragen hat, aber ein ähnliches Problem aufgedeckt und verhindert eine Implementierung (aktualisiert hier).

Die Direktive Rendern HTML, die Angular {{expressions}} enthält, die auf Daten zugreifen, die in $scope gespeichert sind. Da die ursprüngliche Lösung war $watch, wenn die Service hatte es Daten bereit. Wie kann ich sicherstellen, dass die "neuen" Daten zu $scopehinzugefügt werden, bevor die Direktive rendert?

Eine Übersicht über die Architektur und die Strömung ist:

  1. ControllerA -> Get Eingabe von Benutzer
  2. ControllerA -> Verwenden Sie Service zu Datentransformation
  3. ControllerB ->$watch für Änderungen in Service
  4. Directive ->$watch für cha nges in Service
  5. ControllerB -> Daten hinzufügen $scope
  6. Directive -> Anzeigedaten transformiert (von Service) Direktiven

Das Problem zwischen den Schritten 5 und 6 ist. Die Direktive rendert {{expressions}}, bevor ControllerB die Daten zu $scope hinzugefügt hat. Auch wenn das funktioniert, fühlt es sich viel zu komplex und 'hacky' an.

In der Tat, ich verwende $watch in ControllerB, um zu warten, wenn die transformierten Daten in einem Dienst bereit sind. Selbst das fühlt sich etwas übertrieben an (der Dienst führt keine asynchronen Anrufe durch).

+0

ich in Winkel bin hier, und auf Ihre Post erhalten, indem Informationen der Suche über Dienste Änderungen in den Richtlinien zu beobachten. Soweit ich sie verstehe (und entsprechend dem, was ich kürzlich gelesen habe), sollten Sie keine Daten zum Scope in Ihrem ** ControllerB ** hinzufügen, Sie sollten es besser dem ** Service ** melden, und zwar wird automatisch an den Bereich ** controllerB ** gemeldet. By the way, Sie können ** Service ** Änderungen in Ihrer ** Richtlinie ** verfolgen (ich meine leicht als Tracking der "externen" ** ControllerB ** Bereich.) Aber vielleicht irre ich mich. –

Antwort

17

Sie können den Dienst bei der Definition der Direktive injizieren und dann einen $watch auf den Daten einrichten.Also in Ihrem Fall:

.directive('tree', function ($compile, myService) { 
    return { 
     // ... 
     link: function (scope, element, attrs) { 
      scope.$watch(function() { 
       return myService.getData(); 
      }, 
      function (newVal) { 
       if (typeof newVal !== 'undefined') { 
        // ... 
       } 
      } 
     }); 
    } 
}); 

Dies wird sehen die Daten für die Änderung, und führen Sie die Datenänderungen der Code jedes Mal.


jedoch , wenn die Daten nicht ändern, nachdem einmal eingestellt wird, ein besserer Weg (sehr effizient) wären ein Versprechen aus dem Dienst zurückzukehren ($http Methoden geben ein Versprechen direkt oder Sie können erstellen Verwenden Sie den Dienst $q) und fügen Sie dann Ihre Berechnung als eine Fortsetzung zu den Daten hinzu.

+1

Danke. Das Problem besteht jedoch darin, dass die ** Anweisung ** Ausdrücke ** ausgibt, die die JSON-Daten im Bereich $ verwenden. Der Code für Ihre ** Anweisung ** wird ausgeführt, wenn ** Service ** aktualisiert wird, aber was ist, wenn er ausgeführt wird, bevor die ** Service ** -Daten in $ scope platziert werden können? Dies geschieht, weil meine Daten von ControllerA abgerufen werden, die Anweisungen jedoch in ControllerB gerendert werden. Ich beobachte 'myService.getData()' in ControllerB und setze die Daten in $ scope. Meine Direktiven werden jedoch gerendert, bevor ControllerB die aktualisierten Daten zu $ ​​scope hinzufügt. – Jack

0

Ich habe eine kurze Funktion geschrieben, mit der Sie Daten in Object einfügen können, ohne sie zu ersetzen. Sie können es in Ihrem Service verwenden. Auf diese Weise brauchen Sie keine Uhr zu verwenden. Sie können die normale Digest-Schleife von Angular verwenden. Zum Beispiel finden Sie in diesem einfachen Controller & Service:

Demo: JSFidde - http://jsfiddle.net/y09kx7f7/1/ mit assert Tests

Controller:

app.controller('dem',function($scope,me){ 
    $scope.user=me.user; // {name:'user name'} 
}) 

Die Steuerung automatisch jedes Mal, ohne Uhr chnage werden Der Benutzername wurde geändert!

Dienst

.factory('me',function($timeout){ 
    var obj={} 
    obj.user={name:'hello'} 
    $timeout(function(){ //Example of change the data 
     newUser={name:'israel'} 
     cloneInto(obj.user,newUser) 
    },1000) 
    return obj 
}) 

Die cloneInto Funktion, die ich geschrieben:

// The function it is like a=b, 
// but keeping the object in his original memory position. 
function cloneInto(a,b){ 
    var i 
    for (i in a){ 
     if(typeof a[i]!='object') //For supporting deep-copy 
      delete a[i] 
    } 
    for (i in b){ 
     if (typeof b[i]=='object'){ 
      if(!a[i]) a[i]={} 
      cloneInto(a[i],b[i]) 
     } 
     else{ 
      a[i]=b[i] 
     } 
    } 
} 
Verwandte Themen