2

I'm using the filter supplied at Angular ng-repeat with nested json objects? to run through my JSON. However, instead of accessing the 2nd level as in the example there, I need to access all of the 3rd level elements.

My JSON looks like:

[
{
    "category": "colors",
    "heading": "Colors & Background",
    "indexes": [
        {
            "index": "colors",
            "name": "Colors",
            "patterns": [
                {
                    "index": "background-patterns",
                    "name": "Background Patterns"
                }
            ]
        }
    ], 
    "order": "1"
},
{
    "category": "typography",
    "heading": "Typography",
    "indexes": [
        {
            "index": "typography",
            "name": "Typography",
            "patterns": [
                {
                    "index": "headings",
                    "name": "Headings"
                },
                {
                    "index": "plain-text",
                    "name": "Plain Text"
                },
                {
                    "index": "text-icon",
                    "name": "Text Icon"
                }
            ]
        }
    ], 
    "order": "2"
}
]

My app.js looks like:

var app = angular.module('mymod', []);

app.filter('createarray', function () {
    return function (value, propertyName) {
        var arrayList = [];
        angular.forEach(value, function (val) {
            angular.forEach(val[propertyName], function (v) {
                arrayList.push(v)
            });
        });
        console.log(arrayList)
        return arrayList;
    }
});

app.directive('everything', function() {
    return {
        restrict: 'E',
        templateUrl: 'everything.html',
        controller: function($scope, $http) {
            $http.get('assets/js/test.json')
                .then(function(result) {
                    $scope.everything = result.data;
                });
        },
        controllerAs: 'everything'
    }
});

And my HTML looks like:

<nav class="om-nav-everything">
    <ul>
        <li ng-repeat="pattern in everything.indexes | createarray: 'patterns'"><a href="index-{{pattern.index}}.html">{{pattern.name}}</a></li>
    </ul>
</nav>

What I want to do is have a list item for every pattern, so a list of all 3rd level items from the JSON.

How would I alter the filter to make this happen?

Here is a Plunker with the relevant code: http://plnkr.co/edit/qY4yoBsGTjl9HsreivAN?p=info

Community
  • 1
  • 1
Bice
  • 149
  • 12

1 Answers1

2

So what I've done is made a function that you can put into the filter, because what's the fun if I do all the work? This will take an array of property names and when it gets to the last one it'll return that value. Here is a plunker to demonstrate http://plnkr.co/edit/K6SJ8wo9q14YXvChxHuP?p=preview

var lastArray = function (arr, propertyNames, index) {
  var res = [];
  if (!Array.isArray(arr)) {
    return res;
  }
  for (var i = 0; i < arr.length; i++) {
    var val = arr[i][propertyNames[index]];
    if (index !== propertyNames.length - 1) {
        var x = index + 1;
        res = res.concat(lastArray(val, propertyNames, x));
    } else {
        res = res.concat(val);
    }
  }
  return res;
};

For a bit of direction I would probably try something like:

<li ng-repeat="o in everything | createarray: 'indexes,patterns'"></li>

Then in the createarray filter split the string on the ',' and send that into lastArray()

Edit: And I did create a plunker to demonstrate it with angular. http://plnkr.co/edit/RsrIAz1Z3i0XFRV4Cj1g?p=preview

Stephen Gilboy
  • 5,572
  • 2
  • 30
  • 36
  • Awesome, I'm 80% of the way there. I have some instances where "indexes" has 2 or more elements (so not just colors, but colors and shades, for example, each with their own patterns). Your solution allows me to grab the first element under 'indexes', can it be enhanced to grab all elements that may live under 'indexes' and their patterns? – Bice Nov 10 '15 at 20:59
  • 1
    It could be but now we're into a specific use case. http://plnkr.co/edit/ZUDrcD?p=preview Here I'm putting the `indexes` object into the result array. The problem with this, though, is that since the property names could differ you'd have a blank `
  • ` if there is no `indexes['name']`. Also, this will add each level. So if you go n levels deep it'll keep adding the parent. But hopefully this is a starting point and you can enhance it.
  • – Stephen Gilboy Nov 10 '15 at 21:24
  • Thanks, I actually meant JSON as I've updated here: http://plnkr.co/edit/qY4yoBsGTjl9HsreivAN?p=info I can try and alter what you've shown, since it's skipping any 'indexes' that have multiple 'index' objects. For example, in the Plunker, the Shades object gets skipped. Definitely not asking you to update, as you've helped immensely already (and you can ignore me anyway!) but I wanted to clarify. – Bice Nov 10 '15 at 21:42