0

I am trying to use ng-repeat to create list of checkboxes for the keys in a nested object.

My object loosk like:

   $scope.kids = [
            { 
                "name": "Will", 
                "age": 6,
                "skills": {
                    "dancing": false,
                    "coloring": true
                }
            },{ 
                "name": "Sally", 
                "age": 7,
                "skills": {
                    "dancing": false,
                    "coloring": true,
                    "runnning": true
                 }
              }
            ];

and I would like a unique list of the keys in the "skills" object with each skill listed only once, not once for each kid. (i.e. "dancing", "coloring", "running")

This was helpful, but I still can't get a unique list after trying the nested repeats

Here's my current attempt on JSFiddle

Thanks!

Community
  • 1
  • 1
Caitlin
  • 11
  • 1
  • What do you mean a unique list? – Zipper Sep 16 '15 at 17:10
  • Why are the skills not an array? – Shak Ham Sep 16 '15 at 17:30
  • By "unique", I mean list each skill only once, i.e. not listing "dancing" twice since it's listed under both kids. – Caitlin Sep 16 '15 at 17:51
  • that changes my interpretation of what you are trying to accomplish, then, and brings up another question. What is the meaning of a checkbox, if you are trying to show only once a key that can appear more than once and have a different value each time? – Claies Sep 16 '15 at 17:57
  • to be honest, the way this data is structured, getting a unique list isn't really practical. – Claies Sep 16 '15 at 17:58
  • Eventually, I'd like to be able to use the checkboxes to filter the list by kids with specific skills, but it looks like this approach may not be practical. – Caitlin Sep 16 '15 at 18:07
  • right, so this is definitely something that can be done, but if your goal is to get a unique group (array, most likely) of skills that are present and then use it in another calculation (filter), then it should be done on the controller, not in the HTML. – Claies Sep 16 '15 at 18:11
  • you actually want to have a separate array for the filter anyway, because if you try to use properties of an array to filter itself, it gets really recursively ugly. – Claies Sep 16 '15 at 18:12
  • Thanks, @Claies, I think that's exactly the info I need! – Caitlin Sep 16 '15 at 18:25

2 Answers2

0

Modify Your HTML

I think you need to change your html, remove your ng-repeats with this

<span ng-repeat="kid in kids">
  <span ng-repeat="(key,skill) in kid.skills">
    <input type="checkbox" ng-modle="{{skill}}"> {{key}}
    <br>
  </span>
</span>

This should give you a list of boxes connected to the correct $scope and titles.

Here is a link to the modified jsfiddle

Edit

I've modified the code to display a list of all the kids and then within that list we have a list of all of the kids individual skills. Its basically about understanding how loops work.

Joe Lloyd
  • 19,471
  • 7
  • 53
  • 81
0

If I got your question correctly, the best solution for you will be to build a filter that extracts the keys, sorts them and pull unique values. Then you can use it in a single repeat. I forked your jsfiddle and added the filter.

I chose to use lodash to quickly pull out the values, flatten, sort and remove dups. Lodash is a huge playground and you could make the filter even more shorthand.

Since you have a repeating access to this filter, I'd suggest you use memoize to avoid redundant evaluation of the filter. Once it is computed, it is good enough. The basic memoization uses a single key and will not be able to account for other parameters but you can override it and take all params into account and have an accurate and efficient memoization.

The filter is defined like so:

mymodule.filter('uniqueKeys', function(){
return function(input, keyPath){
    return _.unique(_.sortBy(_.flatten( _.map(input,
        function(item){return _.keys(_.get(item, keyPath));}))));
}
});

and the repeater would be:

<div ng-repeat="skill in kids | uniqueKeys:'skills'">

Note that I pass in the key to find your values, if you had hobbies field that'd you'd like to extract, you just have to write:

<div ng-repeat="skill in kids | uniqueKeys:'hobbies'">
Meir
  • 14,081
  • 4
  • 39
  • 47