In my model I have data similar to:
$scope.list = [{id:0,tags:['tag1','tag2']},{id:2,tags:['tag2']}};
I want to show a list of tags (contains unique values of 'tag1' and 'tag2') with checkboxes. Hopefully something like:
<div ng-repeat="tag in list.tags">
    <label class="checkbox">
        <input type="checkbox" ng-model="filter.tag" />
        {{tag}}
    </label>
</div>
I know how to filter the main list based on whats checked if I hard code the list, but not how to generate the list of unique tags automatically.
You are looking to perform three operations:
$scope.list
You can do this with pure JavaScript, but to make things easier, I would recommend using Underscore, a library that gives you access to many functions for manipulating and inspecting arrays, objects, and so forth.
Let's start with this code:
$scope.list = [
  {id: 0, tags: ['tag1', 'tag2']},
  {id: 1, tags: ['tag2']},
  {id: 2, tags: ['tag1', 'tag3', 'tag4']},
  {id: 3, tags: ['tag3', 'tag4']}
];
Now, let's perform the first operation: get the array from the tags property for each object in $scope.list. Underscore provides the pluck method, which is just what we need.
pluck
_.pluck(list, propertyName)A convenient version of what is perhaps the most common use-case for map: extracting a list of property values.
Using pluck, we can get the following:
var tags = _.pluck($scope.list, 'tags');
// gives us [['tag1', 'tag2'], ['tag2'], ['tag1', 'tag3', 'tag4'], ['tag3', 'tag4']]
Now, we want to flatten that array.
flatten
_.flatten(array, [shallow])Flattens a nested array (the nesting can be to any depth). If you pass shallow, the array will only be flattened a single level.
tags = _.flatten(tags);
// gives us ['tag1', 'tag2', 'tag2', 'tag1', 'tag3', 'tag4', 'tag3', 'tag4']
Finally, you only want one instance of each tag.
uniq
_.uniq(array, [isSorted], [iterator])Alias:uniqueProduces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
tags = _.unique(tags)
// gives us ['tag1', 'tag2', 'tag3', 'tag4']
We can combine these together with Underscore's useful chain method to chain these together. Let's create a function on the scope that returns the unique tags:
$scope.uniqueTags = function() {
  return _.chain($scope.list)
    .pluck('tags')
    .flatten()
    .unique()
    .value();
};
Since this is a function, it will always return the unique tags, no matter if we add or remove items in $scope.list after the fact.
Now you can use ng-repeat on uniqueTags to show each tag:
<div ng-repeat="tag in uniqueTags()">
  <label class="checkbox">
    <input type="checkbox" ng-model="filter.tag" />
    {{tag}}
  </label>
</div>
Here is a working jsFiddle that demonstrates this technique: http://jsfiddle.net/BinaryMuse/cqTKG/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With