Mam szablon Angular w DOM. Kiedy mój kontroler otrzymuje nowe dane z usługi, aktualizuje model w zakresie $ i ponownie renderuje szablon. Jak dotąd wszystko dobrze.
Problem polega na tym, że muszę wykonać dodatkową pracę po ponownym renderowaniu szablonu i umieszczeniu go w DOM (w tym przypadku wtyczka jQuery).
Wygląda na to, że powinno być jakieś wydarzenie, na przykład AfterRender, ale nie mogę znaleźć czegoś takiego. Być może dobrym rozwiązaniem byłaby dyrektywa, ale wydawało się, że również zaczęła działać zbyt wcześnie.
Oto jsFiddle przedstawiający mój problem: Fiddle-AngularIssue
== AKTUALIZACJA ==
W oparciu o pomocne komentarze odpowiednio zmieniłem dyrektywę na obsługę manipulacji DOM i zaimplementowałem model $ watch wewnątrz dyrektywy. Nadal jednak mam ten sam problem podstawowy; kod wewnątrz zdarzenia $ watch zostanie uruchomiony przed skompilowaniem szablonu i wstawieniem go do DOM, dlatego wtyczka jquery zawsze ocenia pustą tabelę.
Co ciekawe, jeśli usunę wywołanie asynchroniczne, wszystko działa dobrze, więc jest to krok we właściwym kierunku.
Oto mój zaktualizowany Fiddle, aby odzwierciedlić te zmiany: http://jsfiddle.net/uNREn/12/
źródło
Odpowiedzi:
Ten post jest stary, ale zmieniam kod na:
patrz jsfiddle .
Mam nadzieję, że Ci to pomoże
źródło
Po pierwsze, właściwym miejscem na bałagan z renderowaniem są dyrektywy. Radzę zawinąć DOM manipulujący wtyczkami jQuery za pomocą dyrektyw takich jak ta.
Miałem ten sam problem i wymyśliłem ten fragment kodu. Wykorzystuje
$watch
i$evalAsync
do zapewnienia, że Twój kod działa po rozwiązaniu dyrektyw takichng-repeat
jak{{ value }}
i renderowania szablonów .Mam nadzieję, że pomoże Ci to w uniknięciu niektórych zmagań.
źródło
link
funkcję ztemplateUrl
.Zgodnie z radą Misko, jeśli chcesz wykonać operację asynchroniczną, zamiast $ timeout () (która nie działa)
użyj $ evalAsync () (która działa)
Fiddle . Dodałem również link „usuń wiersz danych”, który zmodyfikuje $ scope.assignments, symulując zmianę danych / modelu - aby pokazać, że zmiana danych działa.
W sekcji Środowisko wykonawcze strony Przegląd koncepcyjny wyjaśniono, że evalAsync należy stosować, gdy potrzebujesz czegoś poza bieżącą ramką stosu, ale przed renderowaniem przeglądarki. (Zgadywanie tutaj ... „bieżąca ramka stosu” prawdopodobnie zawiera aktualizacje Angular DOM.) Użyj limitu czasu $, jeśli potrzebujesz czegoś po renderowaniu przeglądarki.
Jednak, jak już się dowiedziałeś, nie sądzę, aby była tu potrzeba operacji asynchronicznej.
źródło
$scope.$evalAsync($scope.assignmentsLoaded(data));
nie ma żadnego sensu IMO. Argumentem za$evalAsync()
powinna być funkcja. W twoim przykładzie wywołujesz funkcję w momencie, gdy funkcja powinna zostać zarejestrowana do późniejszego wykonania.Odkryłem, że najprostszym (tanim i wesołym) rozwiązaniem jest po prostu dodanie pustego zakresu za pomocą ng-show = "someFunctionThatAlwaysReturnsZeroOrNothing ()" na końcu ostatniego renderowanego elementu. Ta funkcja zostanie uruchomiona, aby sprawdzić, czy powinien zostać wyświetlony element zakresu. Wykonaj dowolny inny kod w tej funkcji.
Zdaję sobie sprawę, że nie jest to najbardziej elegancki sposób na robienie rzeczy, jednak działa dla mnie ...
Miałem podobną sytuację, choć nieco odwróconą, gdy musiałem usunąć wskaźnik ładowania, gdy animacja się rozpoczęła, na urządzeniach mobilnych kątowanie inicjowało się znacznie szybciej niż animacja, która ma być wyświetlana, a użycie płaszcza ng było niewystarczające, ponieważ wskaźnik ładowania był usunięte na długo przed wyświetleniem jakichkolwiek rzeczywistych danych. W tym przypadku właśnie dodałem funkcję return 0 do pierwszego renderowanego elementu iw tej funkcji odwróciłem var, który ukrywa wskaźnik ładowania. (oczywiście dodałem ng-hide do wskaźnika ładowania wyzwalanego przez tę funkcję.
źródło
$anchorScroll
wezwania wbudowanej usługi po renderowaniu DOM i nic nie poradziło na to poza tym. Hackish, ale działa.Myślę, że szukasz $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync
źródło
W końcu znalazłem rozwiązanie, korzystałem z usługi REST do aktualizacji mojej kolekcji. Aby przekonwertować jquery bazującą na danych, należy wykonać następujący kod:
źródło
musiałem to robić dość często. Mam dyrektywę i muszę zrobić kilka rzeczy po tym, jak model zostanie w pełni załadowany do DOM. więc umieszczam moją logikę w linku: funkcja dyrektywy i zawijam kod w setTimeout (function () {.....}, 1); setTimout zostanie uruchomiony po załadowaniu DOM, a 1 milisekunda to najkrótszy czas po załadowaniu DOM, zanim kod zostanie wykonany. wydaje mi się, że to działa, ale chciałbym, aby kątowe wywołało zdarzenie, gdy szablon został załadowany, aby dyrektywy używane przez ten szablon mogły wykonywać zapytania i uzyskiwać dostęp do elementów DOM. mam nadzieję że to pomoże.
źródło
Możesz także utworzyć dyrektywę, która uruchamia kod w funkcji link.
Zobacz tę odpowiedź Stackoverflow .
źródło
Ani $ scope. $ EvalAsync () ani $ timeout (fn, 0) nie działały dla mnie niezawodnie.
Musiałem połączyć te dwa. Stworzyłem dyrektywę, a dla dobrego pomiaru nadałem priorytet wyższy niż domyślna wartość. Oto jego instrukcja (uwaga: używam ngInject do wstrzykiwania zależności):
Aby wywołać dyrektywę, zrobiłbyś to:
Jeśli chcesz go wywołać po zakończeniu działania powtórzenia ng, dodałem pusty zakres w moim powtórzeniu ng i ng-if = "$ last":
źródło
W niektórych scenariuszach, w których aktualizujesz usługę i przekierowujesz do nowego widoku (strony), a następnie dyrektywa jest ładowana przed aktualizacją usług, możesz użyć $ rootScope.
Widok
Kontroler
Dyrektywa
źródło
Przyszło mi całkiem proste rozwiązanie. Nie jestem pewien, czy jest to właściwy sposób, ale działa w sensie praktycznym. Zobaczmy bezpośrednio, co chcemy renderować. Na przykład w dyrektywie, która zawiera niektóre
ng-repeat
s, uważałbym na długość tekstu (możesz mieć inne rzeczy!) Akapitów lub całego HTML. Dyrektywa będzie taka:UWAGA: kod faktycznie działa po renderowaniu zmian raczej po całkowitym renderowaniu. Ale wydaje mi się, że w większości przypadków możesz poradzić sobie z sytuacjami za każdym razem, gdy pojawią się zmiany renderowania. Możesz również pomyśleć o porównaniu tej
p
długości (lub dowolnej innej miary) z modelem, jeśli chcesz uruchomić kod tylko raz po zakończeniu renderowania. Doceniam wszelkie przemyślenia / komentarze na ten temat.źródło
Możesz użyć modułu „jQuery Passthrough” narzędzi angular -ui . Z powodzeniem powiązałem wtyczkę karuzeli dotykowej jQuery z niektórymi obrazami, które pobieram asynchronicznie z usługi sieciowej i renderuję za pomocą ng-repeat.
źródło