14

私のモデルには、次のようなデータがあります。

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

チェックボックス付きのタグ(「tag1」と「tag2」の一意の値を含む)のリストを表示したい。うまくいけば、次のようなものです。

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

リストをハードコーディングした場合にチェックされた内容に基づいてメインリストをフィルタリングする方法は知っていますが、一意のタグのリストを自動的に生成する方法はわかりません。

4

2 に答える 2

27

次の3つの操作を実行しようとしています。

  • の各アイテムからタグの配列を取得します$scope.list
  • これらを単一の配列にフラット化します
  • この配列から一意の値を取得します

これは純粋なJavaScriptで行うことができますが、作業を簡単にするために、配列やオブジェクトなどを操作および検査するための多くの関数にアクセスできるライブラリであるアンダースコアを使用することをお勧めします。

このコードから始めましょう:

$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。アンダースコアはpluckメソッドを提供します。これはまさに私たちが必要としているものです。

摘む _.pluck(list, propertyName)

マップのおそらく最も一般的なユースケースの便利なバージョン:プロパティ値のリストの抽出。

pluckを使用すると、次のようになります。

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

次に、その配列をフラット化します。

平らにする _.flatten(array, [shallow])

ネストされた配列をフラット化します(ネストは任意の深さにすることができます)。浅く通過すると、配列は1レベルだけ平坦化されます。

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

最後に、各タグのインスタンスは1つだけ必要です。

uniq _.uniq(array, [isSorted], [iterator])エイリアス:unique

===を使用してオブジェクトの同等性をテストし、重複のないバージョンの配列を生成します。配列がソートされていることが事前にわかっている場合、isSortedにtrueを渡すと、はるかに高速なアルゴリズムが実行されます。変換に基づいて一意のアイテムを計算する場合は、イテレータ関数を渡します。

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

これらをUnderscoreの便利な方法と組み合わせて、これらchainを連鎖させることができます。一意のタグを返すスコープ上に関数を作成しましょう。

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

これは関数であるため、事後にアイテムを追加または削除しても、常に一意のタグが返されます$scope.list

ng-repeatこれで、を使用しuniqueTagsて各タグを表示できます。

<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/

于 2013-01-04T20:27:58.613 に答える
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">

フィドル


以下は、おそらくあなたが望んでいる/期待していると私が思うことをしないかもしれません:

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

filter.tag1これは $scope プロパティを作成せずfilter.tag2、コントローラ スコープ (つまり、ng-repeat が使用されるスコープ) に作成します。ng-repeat の各反復は独自の子スコープを作成するため、上記の ng-modelfilter.tagは、私のフィドルに示すように、各 ng-repeat 子スコープにスコープ プロパティを作成します。

于 2013-01-04T22:58:53.573 に答える