2013-07-26 9 views
6

Sto provando a creare una direttiva personalizzata che riorganizza il contenuto come una griglia. Voglio escludere il risultato di una direttiva ng-repeat e quindi riordinare gli elementi risultanti.Come posso ottenere un handle sugli elementi figli di ng-repeat nella mia direttiva personalizzata?

Il problema è quando chiamo il metodo element.children() all'interno della funzione di collegamento, ho un array vuoto perché la direttiva ng-repeat non è ancora stata sottoposta a rendering e viene interpretata come un commento.

In caso contrario, la direttiva funziona in modo ottimale se il suo contenuto è "statico".

Il codice HTML

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

mia direttiva con solo le interessanti pezzi di codice:

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(); 

      // ... 
    }; 
}]); 

Che cosa mi manca?

+2

All'interno della vostra funzione di collegamento che si può provare a utilizzare $ timout (function() {// Accesso alla Rete bambini}, 0); – Chandermani

+0

Questo funziona davvero, ma questo metodo è affidabile? –

+0

In realtà il modello secondario viene sottoposto a rendering dopo la funzione di post-link, quindi è necessario aggiungere $ timout, funzionerà in quanto introduce qualche ritardo. – Chandermani

risposta

0

Per raggiungere riordino, sono disponibili diverse opzioni:

  1. manipolare DOM. IMHO, questo è il modo meno preferito, non è molto angoloso.
  2. Riordinare l'array ([1, 2, 3]) utilizzato in ngRepeat nella funzione di collegamento.
  3. Usa orderBy filtro (doc)

Ho creato un Plunk per dimostrare 2 e 3, spero che possa aiutare. http://plnkr.co/edit/vrgeBoJZiG6WMu4Rk46u?p=preview

+0

Forse ti ho ingannato con il termine 'riordino'. Il mio obiettivo era più di riorganizzare gli elementi come una griglia (per esempio 3 elementi/riga). Comunque grazie ;) –

0

Ci sono un paio di modi per avvicinarsi a questo. La soluzione più semplice e più comune che vedrete è come commenti suggeriscono - leva $timeout come tale ...

.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], [ritardo], [invokeApply], [pass]);

[...]

invokeApply - Se impostato salta falso model checking sporca, altrimenti richiamerà fn all'interno del $ applicare blocco. (predefinito: true)

Calling $timeout forzerà un ciclo $digest - quindi per il momento si accede i bambini - la direttiva ng-repeat sarà "fatto". La corsa con ng-repeat è il nocciolo del problema qui - perché sta ancora facendo il suo lavoro quando entriamo nella nostra funzione link.


Un altro modo è possibile risolvere questo - che è certamente meno comune - ma fa un grande lavoro di illustrare una sequenza più dettagliata degli eventi, è la seguente ...

.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'); 
     } 
    }; 
}]); 

Eccoci estensione discreta ng-repeat per richiamare una funzione al completamento - e possiamo sottoscrivere questo tramite $on nella nostra funzione link.


JSFiddle Link - semplice demo in mostra entrambi gli approcci

Problemi correlati