2013-07-26 8 views
6

Próbuję utworzyć niestandardową dyrektywę, która zmienia jej zawartość jako siatkę. Chcę przetłumaczyć wynik dyrektywy ng-repeat, a następnie zmienić kolejność elementów wynikowych.Jak uzyskać uchwyt elementów potomnych powtarzających ng w mojej dyrektywie niestandardowej?

Problem polega na tym, że wywołuję metodę element.children() w funkcji łącza, mam pustą tablicę, ponieważ dyrektywa ng-repeat nie jest jeszcze renderowana i jest interpretowana jako komentarz.

W przeciwnym razie dyrektywa działa świetnie, jeśli jej zawartość jest "statyczna".

HTML

<grid n='6'> 
    <div ng-repeat="i in [1,2,3]"></div> 
</grid> 

Moja dyrektywa tylko z ciekawszych kawałków kodu:

app.directive('grid', [function() { 
    return { 

     restrict: 'E', 
     replace: true, 
     transclude: true, 
     template: "<div ng-transclude></div>", 

     link: function (scope, grid, attrs) { 

      // With an ngRepeat transcluded, els result in an empty array 
      var els = grid.children(); 

      // ... 
    }; 
}]); 

Czego mi brakuje?

+2

W ramach swojej funkcji łącza można spróbować użyć $ Timout (function() {// grid dostępu dzieci}, 0); – Chandermani

+0

To rzeczywiście działa, ale czy ta metoda jest niezawodna? –

+0

Rzeczywiście, szablon podrzędny zostanie zrenderowany po funkcji łączenia postów, więc musisz dodać wartość $ timout, to działałoby, ponieważ wprowadza pewne opóźnienie. – Chandermani

Odpowiedz

0

Aby osiągnąć zmianę kolejności, masz kilka opcji:

  1. manipulować DOM. IMHO, jest to najmniej preferowany sposób, nie jest bardzo kanciasty.
  2. Zamów ponownie tablicę ([1, 2, 3]), która jest używana w ngRepeat w funkcji łączenia.
  3. Zastosowanie orderBy filtr (doc)

Utworzyłem upadać wykazania 2 i 3, nadzieję, że może pomóc. http://plnkr.co/edit/vrgeBoJZiG6WMu4Rk46u?p=preview

+0

Mogłem wprowadzić Cię w błąd z terminem "przerejestruj". Moim celem było raczej przestawienie elementów w siatkę (na przykład 3 elementy/rząd). Mimo wszystko dziękuję ;) –

0

Istnieje kilka sposobów podejścia do tego. Najprostszym i najczęstszym rozwiązaniem widać to jak komentarze sugerują - dźwignia $timeout jako takie ...

.directive('grid', ['$timeout', function ($timeout) { 
    return { 
     restrict: 'E', 
     replace: true, 
     transclude: true, 
     template: '<div ng-transclude></div>', 
     link: function (scope, grid, attrs) { 
      $timeout(function() { 
       console.log(grid.children()); 
      }); 
     } 
    } 
}]); 

$ Timeout ([Fn] [Opóźnienie], [invokeApply], [Przełęcz]);

[...]

invokeApply - Jeśli ustawiona na false modelu przeskakuje brudnej kontroli, w przeciwnym razie będzie wywoływał fn obrębie $ zastosować blok. (domyślna: true)

Wywołanie $timeout wymusi cykl $digest - tak przez czas logowania dzieci - dyrektywa ng-repeat będzie „zrobione”. Wyścig z numerem ng-repeat stanowi sedno problemu - ponieważ nadal wykonuje on swoją pracę, zanim wejdziemy w naszą funkcję link.


Inny sposób można rozwiązać ten problem - co z pewnością jest mniej powszechne - ale robi wielką pracę na ilustrujący bardziej szczegółową sekwencję zdarzeń, przedstawia się następująco ...

.directive('grid', [function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     transclude: true, 
     template: '<div ng-transclude></div>', 
     link: function (scope, grid, attrs) { 
      scope.$on('repeat-done', function() { 
       console.log(grid.children()); 
      }); 
     } 
    } 
}]) 
.directive('ngRepeat', [function() { 
    return { 
     restrict: 'A', 
     link: function (scope, elem, attrs) { 
      if (scope.$last) 
       scope.$root.$broadcast('repeat-done'); 
     } 
    }; 
}]); 

Tu jesteśmy dyskretnie rozszerzając numer ng-repeat, aby wywołać funkcję po zakończeniu - i możemy zapisać się do tego poprzez $on w naszej funkcji link.


JSFiddle Link - proste demo prezentujący zarówno zbliża

Powiązane problemy