2013-01-04 16 views
14

w moim modelu mam danych podobnych do:Pokaż listę zagregowane w angularjs

$scope.list = [{id:0,tags:['tag1','tag2']},{id:2,tags:['tag2']}}; 

chcę pokazać listę tagów (zawiera unikalne wartości „Tag1” i „tag2”) z wyboru. Mam nadzieję, że coś takiego:

<div ng-repeat="tag in list.tags"> 
    <label class="checkbox"> 
     <input type="checkbox" ng-model="filter.tag" /> 
     {{tag}} 
    </label> 
</div> 

wiem jak filtrować główną listę na podstawie co jest sprawdzane, czy ja ciężko kod lista, ale nie jak wygenerować listę unikalnych tagów automatycznie.

Odpowiedz

26

Szukasz wykonać trzy operacje:

  • uzyskać tablicę tagów z każdej pozycji w $scope.list
  • wyprostuj je w jednej tablicy
  • Get unikalne wartości z tej tablicy

Możesz to zrobić za pomocą czystego JavaScriptu, ale aby ułatwić sobie pracę, polecam użyć biblioteki Underscore, która zapewnia dostęp do wielu atrakcji uprawnienia do manipulowania i sprawdzania tablic, obiektów i tak dalej.

Zacznijmy od tego kodu:

$scope.list = [ 
    {id: 0, tags: ['tag1', 'tag2']}, 
    {id: 1, tags: ['tag2']}, 
    {id: 2, tags: ['tag1', 'tag3', 'tag4']}, 
    {id: 3, tags: ['tag3', 'tag4']} 
]; 

A teraz przeprowadzić pierwszą operację: uzyskać tablicę z właściwości dla każdego obiektu w $scope.listtags. Podkreślenie zapewnia metodę pluck, której właśnie potrzebujemy.

oskubać_.pluck(list, propertyName)

Dogodnym wersja tego, co jest chyba najbardziej powszechne stosowanie literami na mapie: wydobywania listę wartości nieruchomości.

Korzystanie podroby, możemy uzyskać następujące:

var tags = _.pluck($scope.list, 'tags'); 
// gives us [['tag1', 'tag2'], ['tag2'], ['tag1', 'tag3', 'tag4'], ['tag3', 'tag4']] 

Teraz chcemy spłaszczyć tę tablicę.

spłaszczenia_.flatten(array, [shallow])

Spłaszcza zagnieżdżonej tablicy (zagnieżdżenia może mieć na każdej głębokości). Jeśli przejdziesz płytko, tablica zostanie spłaszczona tylko na jednym poziomie.

tags = _.flatten(tags); 
// gives us ['tag1', 'tag2', 'tag2', 'tag1', 'tag3', 'tag4', 'tag3', 'tag4'] 

Wreszcie, chcą tylko jedno wystąpienie każdego znacznika.

uniq_.uniq(array, [isSorted], [iterator]) alias: unique

Wytwarza duplikat wolne wersji tablicy, stosując === testować równości obiektów. Jeśli wiesz wcześniej, że tablica jest posortowana, podanie wartości true dla metody isSorted spowoduje uruchomienie znacznie szybszego algorytmu.Aby obliczyć unikalne elementy na podstawie transformacji, należy przekazać funkcję iteratora.

tags = _.unique(tags) 
// gives us ['tag1', 'tag2', 'tag3', 'tag4'] 

Możemy połączyć je razem z użytecznego chain sposobu podkreślenia do łańcucha je razem. Stwórzmy funkcję w sprawie zakresu, która zwraca unikalne tagi:

$scope.uniqueTags = function() { 
    return _.chain($scope.list) 
    .pluck('tags') 
    .flatten() 
    .unique() 
    .value(); 
}; 

Ponieważ jest to funkcja, to zawsze powrócić unikalne znaczniki, bez względu na to, czy mamy dodawać lub usuwać elementy w $scope.list po fakcie.

Teraz można użyć ng-repeat na uniqueTags pokazać każdy tag:

<div ng-repeat="tag in uniqueTags()"> 
    <label class="checkbox"> 
    <input type="checkbox" ng-model="filter.tag" /> 
    {{tag}} 
    </label> 
</div> 

Oto pracuje jsFiddle który demonstruje tę technikę: http://jsfiddle.net/BinaryMuse/cqTKG/

+0

Idealny! I świetne wyjaśnienie! –

+0

Dzięki! Chętnie pomogłem.^_^ –

+0

Jaka jest wydajność podobna do używania takiej funkcji agregacji? Jak często Angular będzie wywoływał tę funkcję? – oldwizard

3

użyć filtru niestandardowego, aby uzyskać niepowtarzalny komplet/tablicę tagi, odpowiednie do użycia z powtórzeniem ng:

.filter('uniqueTags', function() { 
    return function(list) { 
     var tags = {}; 
     angular.forEach(list, function(obj, key) { 
      angular.forEach(obj.tags, function(value) { 
       tags[value] = 1; 
      }) 
     }); 
     var uniqueTags = [] 
     for (var key in tags) { 
      uniqueTags.push(key); 
     } 
     return uniqueTags; 
    } 
}); 

Najpierw umieściłem tagi w obiekcie, który automatycznie Tically daje nam wyjątkowość. Następnie konwertuję go do tablicy.

Zastosowanie następująco:

<div ng-repeat="tag in list | uniqueTags"> 

Fiddle.


Mogą nie robić to, co myślę, że prawdopodobnie chcesz/liczą to zrobić:

<input type="checkbox" ng-model="filter.tag"> 

nie tworzyć właściwości $, zakres filter.tag1 i filter.tag2 zakresu regulatora (czyli zakres gdzie użyte jest powtórzenie ng). Każda iteracja polecenia ng-repeat tworzy własny zakres podrzędny, więc powyższy model ng utworzy właściwość zakresu filter.tag dla każdego zakresu potomnego powtarzania ng, jak pokazano w moim skrzypcach.

Powiązane problemy