Ich habe eine Winkelvorlage im DOM. Wenn mein Controller neue Daten von einem Dienst erhält, aktualisiert er das Modell im Bereich $ und rendert die Vorlage erneut. Alles gut soweit.
Das Problem ist, dass ich auch zusätzliche Arbeit leisten muss, nachdem die Vorlage neu gerendert wurde und sich im DOM befindet (in diesem Fall ein jQuery-Plugin).
Es scheint, als sollte es ein Ereignis geben, das man sich anhören kann, wie AfterRender, aber ich kann so etwas nicht finden. Vielleicht wäre eine Richtlinie ein guter Weg, aber sie schien auch zu früh zu feuern.
Hier ist eine jsFiddle, die mein Problem umreißt: Fiddle-AngularIssue
== UPDATE ==
Aufgrund hilfreicher Kommentare habe ich entsprechend zu einer Direktive gewechselt, um die DOM-Manipulation zu handhaben, und ein Modell $ watch in die Direktive implementiert. Ich habe jedoch immer noch das gleiche Grundproblem. Der Code innerhalb des $ watch-Ereignisses wird ausgelöst, bevor die Vorlage kompiliert und in das DOM eingefügt wurde. Daher wertet das jquery-Plugin immer eine leere Tabelle aus.
Interessanterweise funktioniert das Ganze einwandfrei, wenn ich den asynchronen Aufruf entferne. Das ist also ein Schritt in die richtige Richtung.
Hier ist meine aktualisierte Geige, um diese Änderungen widerzuspiegeln: http://jsfiddle.net/uNREn/12/
quelle
Antworten:
Dieser Beitrag ist alt, aber ich ändere Ihren Code in:
siehe jsfiddle .
Ich hoffe es hilft dir
quelle
Erstens sind Direktiven der richtige Ort, um sich mit dem Rendern zu beschäftigen. Mein Rat wäre, DOM-manipulierende jQuery-Plugins durch Anweisungen wie diese zu verpacken.
Ich hatte das gleiche Problem und kam mit diesem Ausschnitt. Es verwendet
$watch
und stellt$evalAsync
sicher, dass Ihr Code ausgeführt wird, nachdem Anweisungen wieng-repeat
aufgelöst und Vorlagen wie{{ value }}
gerendert wurden.Ich hoffe, dies kann Ihnen helfen, einen Kampf zu verhindern.
quelle
link
Funktion auch mit a kombinieren könnentemplateUrl
.Befolgen Sie die Anweisungen von Misko, wenn Sie eine asynchrone Operation wünschen, statt $ timeout () (was nicht funktioniert).
benutze $ evalAsync () (was funktioniert)
Geige . Ich habe auch einen Link "Datenzeile entfernen" hinzugefügt, der $ scope.assignments ändert und eine Änderung an den Daten / dem Modell simuliert - um zu zeigen, dass das Ändern der Daten funktioniert.
Im Abschnitt " Laufzeit " der Seite "Konzeptionelle Übersicht" wird erläutert, dass evalAsync verwendet werden sollte, wenn etwas außerhalb des aktuellen Stapelrahmens auftreten muss, jedoch bevor der Browser gerendert wird. (Vermutung hier ... "aktueller Stapelrahmen" enthält wahrscheinlich Angular DOM-Updates.) Verwenden Sie $ timeout, wenn nach dem Rendern des Browsers etwas auftreten muss.
Wie Sie jedoch bereits herausgefunden haben, besteht hier meines Erachtens keine Notwendigkeit für einen asynchronen Betrieb.
quelle
$scope.$evalAsync($scope.assignmentsLoaded(data));
macht keinen Sinn IMO. Das Argument für$evalAsync()
sollte eine Funktion sein. In Ihrem Beispiel rufen Sie die Funktion zu dem Zeitpunkt auf, zu dem eine Funktion für die spätere Ausführung registriert werden soll.Ich habe festgestellt, dass die einfachste (billige und fröhliche) Lösung darin besteht, einfach eine leere Spanne mit ng-show = "someFunctionThatAlwaysReturnsZeroOrNothing ()" am Ende des zuletzt gerenderten Elements hinzuzufügen. Diese Funktion wird ausgeführt, wenn geprüft wird, ob das span-Element angezeigt werden soll. Führen Sie einen anderen Code in dieser Funktion aus.
Mir ist klar, dass dies nicht die eleganteste Art ist, Dinge zu tun, aber es funktioniert für mich ...
Ich hatte eine ähnliche Situation, obwohl sie leicht umgekehrt war, als ich zu Beginn einer Animation eine Ladeanzeige entfernen musste. Auf Mobilgeräten wurde der Winkel viel schneller initialisiert als die anzuzeigende Animation, und die Verwendung eines ng-Umhangs war nicht ausreichend, da die Ladeanzeige war entfernt, lange bevor echte Daten angezeigt wurden. In diesem Fall habe ich gerade die Funktion my return 0 zum ersten gerenderten Element hinzugefügt und in dieser Funktion die Variable umgedreht, die den Ladeindikator verbirgt. (Natürlich habe ich der durch diese Funktion ausgelösten Ladeanzeige ein ng-hide hinzugefügt.
quelle
$anchorScroll
Dienst, um nach dem Rendern des DOM aufgerufen zu werden, und nichts schien den Trick zu tun, außer dies. Hackish aber funktioniert.Ich denke, Sie suchen nach $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync
quelle
Schließlich fand ich die Lösung, ich verwendete einen REST-Service, um meine Sammlung zu aktualisieren. Um eine datierbare Abfrage zu konvertieren, ist der folgende Code:
quelle
Ich musste das ziemlich oft tun. Ich habe eine Direktive und muss einige JQuery-Sachen machen, nachdem Model-Sachen vollständig in das DOM geladen sind. Also habe ich meine Logik in den Link gesetzt: Funktion der Direktive und den Code in ein setTimeout (function () {.....}, 1) einschließen; Das setTimout wird ausgelöst, nachdem das DOM geladen wurde, und 1 Millisekunde ist die kürzeste Zeit nach dem Laden des DOM, bevor der Code ausgeführt wird. Dies scheint für mich zu funktionieren, aber ich wünschte, Angular hätte ein Ereignis ausgelöst, sobald eine Vorlage geladen wurde, damit die von dieser Vorlage verwendeten Anweisungen Abfragen ausführen und auf DOM-Elemente zugreifen können. hoffe das hilft.
quelle
Sie können auch eine Direktive erstellen, die Ihren Code in der Link-Funktion ausführt.
Siehe diese Stackoverflow-Antwort .
quelle
Weder $ scope. $ EvalAsync () noch $ timeout (fn, 0) haben bei mir zuverlässig funktioniert.
Ich musste beides kombinieren. Ich habe eine Direktive erstellt und auch eine Priorität höher als den Standardwert für eine gute Maßnahme gesetzt. Hier ist eine Anweisung dafür (Hinweis: Ich verwende ngInject, um Abhängigkeiten einzufügen):
Um die Richtlinie aufzurufen, würden Sie Folgendes tun:
Wenn Sie es aufrufen möchten, nachdem eine ng-Wiederholung ausgeführt wurde, habe ich eine leere Spanne in meine ng-Wiederholung und ng-if = "$ last" eingefügt:
quelle
In einigen Szenarien, in denen Sie einen Dienst aktualisieren und zu einer neuen Ansicht (Seite) umleiten und dann Ihre Direktive geladen wird, bevor Ihre Dienste aktualisiert werden, können Sie $ rootScope. $ Broadcast verwenden, wenn Ihre $ watch oder $ timeout fehlschlägt
Aussicht
Regler
Richtlinie
quelle
Ich kam mit einer ziemlich einfachen Lösung. Ich bin mir nicht sicher, ob es der richtige Weg ist, aber es funktioniert im praktischen Sinne. Lassen Sie uns direkt beobachten, was gerendert werden soll. Zum Beispiel
ng-repeat
würde ich in einer Direktive, die einige s enthält, auf die Länge des Textes (Sie haben vielleicht andere Dinge!) Von Absätzen oder des gesamten HTML-Codes achten. Die Richtlinie wird folgendermaßen aussehen:HINWEIS : Der Code wird nach dem Rendern tatsächlich ausgeführt. Änderungen sind eher vollständig. Aber ich denke, in den meisten Fällen können Sie mit den Situationen umgehen, wenn Änderungen beim Rendern auftreten. Sie können diese
p
Länge (oder eine andere Kennzahl) auch mit Ihrem Modell vergleichen, wenn Sie Ihren Code nach Abschluss des Renderns nur einmal ausführen möchten . Ich freue mich über alle Gedanken / Kommentare dazu.quelle
Sie können das Modul 'jQuery Passthrough' der Angular-UI-Utils verwenden . Ich habe erfolgreich ein jQuery Touch-Karussell-Plugin an einige Bilder gebunden, die ich asynchron von einem Webdienst abrufe, und sie mit ng-repeat gerendert.
quelle