user2756091 user2756091 - 2 months ago 11
reST (reStructuredText) Question

Angular - Loop through unique items from REST data

I am trying to iterate through unique "modules" that are received through REST services. There are multiple href's that are associated with a single module.

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<script type="text/javascript">

var moduleServiceUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/lists/getbytitle('Pages')/Items?$select=ID,Title,FileRef,Modules";
var appVar = angular.module('listApp', []);

appVar.controller('controller1', function ($scope, $http) {
$http({
method: 'GET',
url: moduleServiceUrl,
headers: { "Accept": "application/json;odata=verbose" }
}).success(function (data, status, headers, config) {
$scope.items = data.d.results;

});
})
</script>

</head>
<body>
<hr />
<div ng-app="listApp">
<div id="App1" ng-controller="controller1">
<div ng-repeat="item in items" ng-if="item.Modules">
<b><p>{{item.Modules}}</p></b>
<p class="kbRelatedArticle" style="padding-left:10px"><a href="{{item.FileRef}}">{{item.Title}}</a></p>
</div>

</div>
</div>

</body>
</html>


Here is what the current output looks like

My goal is to have all the links under the same module heading instead of having repeated module headings.

My initial thought was to have a nested ng-repeat in which the outer ng-repeat would loop through the unique modules and the inner would then generate the links that are related to that module.

Answer

You can create an object with Modules as the key and an array of items as the value like so

$scope.modules = data.d.results.reduce((modules, item) => {
    if (item.Modules) {
        if (Array.isArray(modules[item.Modules])) {
            modules[item.Modules].push(item);
        } else {
            modules[item.Modules] = [item];
        }
    }
    return modules;
}, Object.create(null));

Or if you're not against using something like Lodash

$scope.modules = _.groupBy(data.d.results, 'Modules');

Then your HTML can use a nested repeater

<div ng-repeat="(module, items) in modules">
    <p><strong>{{module}}</strong></p>
    <p ng-repeat="item in items" style="padding-left:10px;">
        <a ng-href="{{item.FileRef}}">{{item.Title}}</a>
    </p>
</div>
Comments