Given a list of items displayed with ng-repeat I want to display extra stuff whenever a value in a column changes, eg:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.cards = [
{suit: 'Hearts', value: 7},
{suit: 'Clubs', value: 7},
{suit: 'Spades', value: 7},
{suit: 'Diamonds', value: 7},
{suit: 'Hearts', value: 8},
{suit: 'Clubs', value: 8},
{suit: 'Spades', value: 8},
{suit: 'Diamonds', value: 8},
{suit: 'Hearts', value: 9},
{suit: 'Clubs', value: 9},
{suit: 'Spades', value: 9},
{suit: 'Diamonds', value: 9} ];
$scope.myValueFunction = function(card) {
return [card.suit, card.value];
};
}
I need the following result:
The Clubs
7
8
9
The Diamonds
7
8
9
The Hearts
7
8
9
The Spades
7
8
9
I would prefer to have a HTML something like that:
<div ng-controller="MyCtrl">
<div ng-repeat="card in cards | orderBy:myValueFunction">
<div break-on-column="card.suit">The {{card.suit}}</div>
<div>{{card.value}}</div>
</div>
</div>
Of course, the real problem contains many columns (not just two), several break columns (eg: break-on-column="col1,col2,col3"), the break columns are not fixed (ie. the are chosen by the user at runtime).
I would preprocess the array the way that it displays the data the what you need. I don't think that the ng-repeat directive is capable of such things.
Another idea could be to write a custom function for displaying information like so:
HTML
<div ng-controller="MyCtrl">
<div ng-repeat="card in cards | orderBy:myValueFunction">
<data-displaying></data-displaying>
</div>
</div>
Directive
.directive('dataDisplaying', function() {
return {
templateUrl: 'partials/dataTemplate.html',
link: function(scope, element, attrs) {
// Data transformation goes in here
}
}
})
Then you can process the data within the directive and only output a suit (or anything else) when the setting is right. E.g. store the suit temporary and just output it when the suit differs.
I would use ng-hide like this
function MyCtrl($scope) {
//...
$scope.breakProperties = [ 'suit' ];
$scope.breakOn = function(property, index, cards, breakProperties) {
var previousIndex = index - 1;
var propertyPresent = false;
if (previousIndex >= 0) {
var card = cards[index];
var previousCard = cards[previousIndex];
for ( var i = 0; i < breakProperties.length; i += 1) {
if (breakProperties[i] === property) {
propertyPresent = true;
}
}
//if the property is not on the list always show regardless of value
if (!propertyPresent) {
return false;
}
//if the property is different
if (previousCard[property] !== card[property]) {
return false;
}
}
//if it's the first always show
else {
return false;
}
return true;
};
}
The template
<div ng-controller="MyCtrl"
ng-init="orderedCards = cards | orderBy:myValueFunction">
<button ng-click="breakProperties = [ 'suit' ]">Break on suit</button>
<button ng-click="breakProperties = [ 'points' ]">Break on points</button>
<button ng-click="breakProperties = [ 'suit', 'points' ]">Break on
suit and points</button>
<div>{{breakProperties}}</div>
<div ng-repeat="card in orderedCards"
style="border: 1px solid; margin-bottom: 1px;">
<div ng-hide="breakOn('suit', $index, orderedCards, breakProperties)">Suit
{{card.suit}}</div>
<div>Value {{card.value}}</div>
<div ng-hide="breakOn('points', $index, orderedCards, breakProperties)">Points
{{card.points}}</div>
</div>
</div>