1

Using non-3rd party plugins:

I have an array like this:

[
    {groupName:'General', label:'Automatic Updates', type:'select', values:{0:'On', 1:'Off'}},
    {groupName:'General', label:'Restore Defaults', type:'button', values:['Restore']},
    {groupName:'General', label:'Export & Import', type:'button', values:['Export', 'Import']},
    {groupName:'Timing', label:'Double Click Speed', type:'text'},
    {groupName:'Timing', label:'Hold Duration', type:'text'}
]

I want to ng-repeat over this but create groups.

The final result I'm hoping will look like this:

So basically that is a ng-repeat on the groupName to make two div containers, then it ng-repeats for each item within to add the rows.

Is this possible without having to change my array into an object like this:

[
   'General': [...],
   'Timing': [...]
]
Noitidart
  • 35,443
  • 37
  • 154
  • 323
  • Possible duplicate of [Angular ng-repeat conditional wrap items in element (group items in ng-repeat)](http://stackoverflow.com/questions/23493063/angular-ng-repeat-conditional-wrap-items-in-element-group-items-in-ng-repeat) – sirrocco Oct 01 '15 at 04:00

1 Answers1

1

If you want to do something like this, one solution is to split up the repeat into 2 separate repeats. the easiest is to do that by creating a small helper filet that filters out the unique properties. a filter like this would do:

function uniqueFilter() {
    return function(arr,property) {
        if (Object.prototype.toString.call( arr ) !== '[object Array]') {
            return arr;
        }
        if (typeof property !=='string') {
            throw new Error('need a property to check for')
        }
        return Object.keys(arr.reduce(isUn,{}));

        function isUn(obj,item) {
            obj[item[property]] = true;
            return obj;
        }
    }
}

That filter will return an array that consist of the unique values of the property you want to group by.

Once you have this you can nest a couple of ngRepeats like this:

<div ng-repeat="group in vm.data| uniqueFilter:'groupName'">
    {{group}}
    <ul>
        <li ng-repeat="item in vm.data| filter:{groupName:group}">{{item.label}}</li>
    </ul>
</div>

And you should be set. There is no need to pull in a 3rth party for this. see it in action in this plunk.

Sander Elias
  • 754
  • 6
  • 9
  • It's been working great and I'm trying to study it, it keeps throwing this even though it works: `Error: arr is undefined` does it do the same for you? Here is my js: https://github.com/Noitidart/MouseControl-v2.0-temp/blob/master/resources/scripts/ng-prefs.js#L130-L143 and here is my ng-repeat its a directive in a directive: https://github.com/Noitidart/MouseControl-v2.0-temp/blob/master/ng-prefs.xhtml#L22 – Noitidart Oct 01 '15 at 14:20
  • Oh this where I use it in the directive: https://github.com/Noitidart/MouseControl-v2.0-temp/blob/master/resources/directives/configWrap.htm#L3 i cant figure out why it says arr is undefined but works :( – Noitidart Oct 01 '15 at 14:29
  • Ah the issue was my variable is undefined on intiail load, and it gets defined later on, so when its undefined how can we make it fail gracefully? Should I `throw` in the filter?\ – Noitidart Oct 01 '15 at 23:48
  • Ah I made it: `if (arr === undeifned) { return }` it seems to fail gracefuly now, meaning no message in error console :) Was this correct move? Thanks for this awesome teaching! – Noitidart Oct 01 '15 at 23:59
  • 1
    Ah, yes, it needs an array to work. Forgot to put in that check. I will adapt the sample and the plunk now. – Sander Elias Oct 06 '15 at 01:38
  • Oh shoot @Sander I found another issue with this. I just found it and am trying to figure out whats up. If we add an item where the string of `group` appears as a substring (case insensitive) in any of the other group names, it gets duplicated, please see plunker: http://plnkr.co/edit/G8z62LBrM432LzaDowRC?p=preview and here is screenshot: http://i.imgur.com/xPhavbg.png there should only be one item in the `T` and `RAL` groups but the items form the `Timing` and `General` groups are getting duplicated into it. – Noitidart Oct 15 '15 at 04:30
  • 1
    Makes sense, T is part of their groupname, so they show, that's how filter works. When you check the docs, you will see that there is a 3rth parameter. If you add :true to your filter it will work. – Sander Elias Oct 16 '15 at 02:59
  • Ahhhh I see thanks!!! `item in vm.data| filter:{groupName:group}:true` fixed it :D – Noitidart Oct 16 '15 at 07:03