To make the design you've outlined, I would suggest doing the following:
Use a filter to "chunk" your articles into groups of 9 (similar to this memoized chunking solution)
Use a custom directive to create your "template"
Leverage a responsive fixed ratio grid system (like cough my library Perfect Bootstrap cough)
Example JSFiddle
Step1
Let's put your JSON back into a standard array, and then "chunk" it into batches of 9 at run time. We create an angular filter that we then apply using | chunk. To avoid an infinite digest loop, we'll need to memoize the result of the function using a variable, in the below code we use the string 'newsGroups'. If you intend to load more items into your array, say for infinite scroll, you'll need to update this variable in order to refresh the memoized result. Think of it like a cachebreak.
For brevity, i have stripped back your article array to be just an id and title item for each element. I would assume this is coming from an AJAX call in your development environment anyways.
HTML
<div class="container-fluid" ng-controller="MyCtrl">
<div class="template-container" ng-repeat="newsGroup in NewsListing | chunk:'newsGroups'">
<!-- content here -->
</div>
</div>
JS Chunk filter and basic array of articles
var myApp = angular.module('myApp', []);
myApp.filter('chunk', function() {
function cacheIt(func) {
cache = {};
return function(arg) {
// if the function has been called with the argument
// short circuit and use cached value, otherwise call the
// cached function with the argument and save it to the cache as well then return
return cache[arg] ? cache[arg] : cache[arg] = func(arg);
};
}
// unchanged from your example apart from we are no longer directly returning this
function chunk(items, chunk_size) {
var chunks = [];
if (angular.isArray(items)) {
if (isNaN(chunk_size))
chunk_size = 9;
for (var i = 0; i < items.length; i += chunk_size) {
chunks.push(items.slice(i, i + chunk_size));
}
} else {
console.log("items is not an array: " + angular.toJson(items));
}
return chunks;
}
// now we return the cached or memoized version of our chunk function
// if you want to use lodash this is really easy since there is already a chunk and memoize function all above code would be removed
// this return would simply be: return _.memoize(_.chunk);
return cacheIt(chunk);
});
myApp.controller('MyCtrl', function($scope) {
$scope.NewsListing = [{
"id": "71b85130-ffe4-11e6-81a4-c1bd97df0d2d",
"title": "Exercitation ullamco laboris"
}, {
"id": "58847180-ffe4-11e6-81a4-c1bd97df0d2d",
"title": "Duis aute irure dolor in reprehenderit"
}, {
"id": "35d2c290-ffe4-11e6-81a4-c1bd97df0d2d",
"title": "Ut enim ad minim"
}, {
"id": "fdbdeb00-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "Ut enim ad minim"
}, {
"id": "df858f30-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "Dolore magna aliqua"
}, {
"id": "bbc619c0-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "Qui officia deserunt mollit anim"
}, {
"id": "8467e800-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "Consectetur adipisicing elit, sed do eiusm"
}, {
"id": "5aea9180-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "Lorem elit, sed do eiusm"
}, {
"id": "418d09c0-ffe3-11e6-81a4-c1bd97df0d2d",
"title": "ALL YOU NEED TO KNOW ABOUT WAREHOUSE"
}, {
"id": "71b85130-ffe4-11e6-81a4-c1bd97df0d2e",
"title": "Exercitation ullamco laboris2"
}, {
"id": "58847180-ffe4-11e6-81a4-c1bd97df0d2e",
"title": "Duis aute irure dolor in reprehenderit2"
}, {
"id": "35d2c290-ffe4-11e6-81a4-c1bd97df0d2e",
"title": "Ut enim ad minim2"
}, {
"id": "fdbdeb00-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "Ut enim ad minim2"
}, {
"id": "df858f30-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "Dolore magna aliqua2"
}, {
"id": "bbc619c0-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "Qui officia deserunt mollit anim2"
}, {
"id": "8467e800-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "Consectetur adipisicing elit, sed do eiusm2"
}, {
"id": "5aea9180-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "Lorem elit, sed do eiusm2"
}, {
"id": "418d09c0-ffe3-11e6-81a4-c1bd97df0d2e",
"title": "ALL YOU NEED TO KNOW ABOUT WAREHOUSE2"
}];
})
Step 2
In the content here comment section of the HTML in Step 1 we would apply a custom directive. In real-life development i would probably use a separate file to hold the template, however, for the constraints of the js fiddle i needed to define it as an text/ng-template script tag.
You can see that the newsGroup from the ng-repeat in Step 1 will be handed to our custom directive using the scope value items. This will contain at most 9 news articles.
HTML Directive call
<div nine-item-news items="newsGroup"></div>
JS directive definition
myApp.directive('nineItemNews', function() {
return {
restrict: 'A',
replace: true,
templateUrl: '/nine-item-news-template.html',
scope: {
items: '='
}
}
});
HTML TEMPLATE
<script type="text/ng-template" id="/nine-item-news-template.html">
<div class="template">
<!-- template content here -->
</div>
</script>
Step 3
A while ago i developed a CSS library designed to provide responsive fixed ratio grid elements. This question has provoked me to finally make it public. Think of it like bootstrap's horizontal col- functionality, but vertically.
We replace the template content here comment above with the following html that will load in the items passed to it by the custom directive from Step 2. I would recommend you expand on this template to add ng-if statements to load/unload blocks, similarly, i would recommend using ng-class to adapt the design for the cases you arent handed a full 9 items (ie. what would it look like if only 6 articles were passed to it). Alternatively, using an ng-switch based on items.length and loading an entirely different template could similarly work.
The additional CSS is to add background colors and remove the default padding/margin for the bootstrap columns.
NB: Please note that in order to make the elements maintain their ratio, their overflow is set to hidden. This works particularly well when items have background images, but can have unintended consequences for text. My example includes a mobile responsivised template design that creates sections with a ration of 2:1. I encourage you to test this for your specific build carefully and a number of screen resolutions.
HTML template content
<div class="row" ng-if="items.length">
<div class="col-xs-12 col-md-4 col-no-padding">
<div class="row-xs-6 row-md-12">
<div class="abs-inner bg-darkgrey">
<p ng-bind="items[0].title"></p>
</div>
</div>
</div>
<div class="col-xs-12 col-md-8 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-grey">
<p ng-bind="items[1].title"></p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-4 col-no-padding">
<div class="row">
<div class="col-xs-12 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-grey">
<p ng-bind="items[2].title"></p>
</div>
</div>
</div>
<div class="col-xs-12 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-midgrey">
<p ng-bind="items[5].title"></p>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-4 col-no-padding">
<div class="row-xs-6 row-md-12">
<div class="abs-inner bg-white">
<p ng-bind="items[3].title"></p>
</div>
</div>
</div>
<div class="col-xs-12 col-md-4 col-no-padding">
<div class="row">
<div class="col-xs-12 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-grey">
<p ng-bind="items[4].title"></p>
</div>
</div>
</div>
<div class="col-xs-12 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-midgrey">
<p ng-bind="items[6].title"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-4 col-no-padding">
<div class="row-xs-6 row-md-12">
<div class="abs-inner bg-darkgrey">
<p ng-bind="items[7].title"></p>
</div>
</div>
</div>
<div class="col-xs-12 col-md-8 col-no-padding">
<div class="row-xs-6">
<div class="abs-inner bg-grey">
<p ng-bind="items[8].title"></p>
</div>
</div>
</div>
</div>
CSS
.col-no-padding{
padding-left:0;
padding-right:0;
}
.col-no-padding > .row{
margin-left:0;
margin-right:0;
}
.bg-darkgrey{
background-color:#535353;
}
.bg-midgrey{
background-color:#808080;
}
.bg-grey{
background-color:#959595;
}
.bg-lightgrey{
background-color:#d0d0d0;
}
.bg-white{
background-color:#FFFFFF;
}