2013-01-04 41 views
14

在我的模型顯示的彙總名單上有相似的數據:在angularjs

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

我想說明的標籤列表(包含「標記1」和「標籤2」的唯一值)與複選框。希望是這樣的:

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

我知道如何根據什麼檢查,如果我硬編碼的列表,而不是如何自動生成唯一標籤的列表過濾的主列表。

回答

26

您正在尋找執行三個操作:在$scope.list

    • 獲取的標籤,從每個項目的數組拼合到這些單個陣列
    • 從這個數組獲取唯一值

    您可以使用純JavaScript來做到這一點,但爲了讓事情更簡單,我建議您使用Underscore,這是一個圖書館,可讓您訪問許多有趣的用於操縱和檢查數組,對象等等。

    讓我們開始使用此代碼:

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

    現在,讓我們執行第一次操作:您可以通過tags屬性爲$scope.list每個對象的數組。 Underscore提供了pluck方法,這正是我們所需要的。

    勇氣_.pluck(list, propertyName)

    什麼是可能是最常見的用例爲圖個方便版本:提取屬性值的列表。

    使用拔毛,我們可以得到以下幾點:

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

    現在,我們要扁平化數組。

    弄平_.flatten(array, [shallow])

    展平嵌套陣列(嵌套可以是任何深度)。如果你傳球較淺,陣列將只能平坦化一個級別。

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

    最後,你只需要每一個標籤的一個實例。

    uniq的_.uniq(array, [isSorted], [iterator])別名:unique

    可生產陣列的無重複的版本,使用===測試對象的相等。如果您事先知道數組已排序,則傳遞true以執行isSorted將運行更快的算法。如果您想基於轉換計算唯一項目,請傳遞迭代器函數。

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

    我們可以一起用下劃線的有用chain方法來鏈接這些結合在一起這些。讓我們對返回的獨特標籤的範圍創建一個函數:

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

    由於這是一個功能,它將始終返回唯一的標籤,無論我們事後在$scope.list添加或刪除項目。

    現在你可以使用ng-repeatuniqueTags顯示每個標籤:

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

    這裏是一個工作的jsfiddle演示此技術:http://jsfiddle.net/BinaryMuse/cqTKG/

  • +0

    完美!還有一個很好的解釋! –

    +0

    謝謝!很高興有幫助。^_^ –

    +0

    使用這種聚合函數的性能如何? Angular多久會調用一次該函數? – oldwizard

    3

    使用自定義過濾器來獲得的唯一的一組/陣列標籤,適用於ng-repeat:

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

    我首先將標籤放入一個對象中,該對象自動從根本上賦予我們獨特性。然後我將它轉換爲一個數組。

    使用方法如下:

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

    Fiddle


    下可能不會做什麼,我想你可能想/希望它做的事:

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

    這不創建$作用域屬性filter.tag1filter.tag2控制器上的範圍(即範圍其中使用ng-repeat)。 ng-repeat的每次迭代都會創建自己的子範圍,因此上面的ng-model將在每個ng-repeat子範圍上創建範圍屬性filter.tag,如我的小提琴中所示。