Reputation: 177
EDIT 2 (ANSWER): For anyone who runs across this looking for a solution to a similar problem, the solution is in the comments under Gianmarco's answer. The productusage
array is pre-processed with the same function as the $scope.alternate
function below, and the result used to set a isAlternate flag on each item in the array. That is then used in either an ng-style or ng-class attribute to determine which styling to use on the row.
EDIT: For clarity: I have groups of RANames where it might go... RAFoo, RAFoo, RABar, RABar, RABar, RABar, RABaz, RABaz, RABaz etc...and I don't want the row to alternate colors until it hits a new RAName. There is a variable number of RAName values with the same RAName, so there could be 2 "RAFoo", 4 "RABar" and 3 "RABaz", etc.. and it can change up.
I have the following code in my controller:
var prevRAName = ""; // intialize prevRAName to empty string
var switchColor = false;
...
$scope.alternate = function (currRAName) {
if (prevRAName) { // starts on 2nd row...
if (currRAName == prevRAName) {
prevRAName = currRAName;
} else {
switchColor = !switchColor;
prevRAName = currRAName;
}
} else {
prevRAName = currRAName; // hits on the first row ...
}
return switchColor;
}
And in the template I have:
<tr ng-repeat="item in productusage | orderBy : ['RAName','PeriodStart']">
<td ng-style="alternate(item.RAName) ? {'background-color':'#f5f5f5'} : {'background-color':'white'}">{{item.RAName}}</td>
<td ng-style="alternate(item.RAName) ? {'background-color':'#f5f5f5'} : {'background-color':'white'}">{{item.ProductDescription}}</td>
<td ng-style="{'background-color': '#' + intToRGB(hashCode(item.PeriodStart)), 'color' : 'white'}">{{item.PeriodCaseCt}}</td>
<td ng-style="{'background-color': '#' + intToRGB(hashCode(item.PeriodStart)), 'color' : 'white'}">{{item.PeriodStart | date : format : shortDate}}</td>
</tr>
I am wanting to alternate the color of the RAName and ProductDescription fields of the table, effectively "grouping" them based on the RAName. The PeriodCaseCt and PeriodCaseCt fields are color coded. Now everything works as is and I wish that this was the end of the story, however I am getting a bunch of these errors:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [[{"msg":"alternate(item.RAName) ? {'background-color':'#f5f5f5'} : {'background-color':'white'}","newVal":{"background-color":"white"},"oldVal":{"background-color":"#f5f5f5"}}
Now, I don't need these values to be watched after the first pass, and it does correctly set everything and the end user would never know unless they had the developer tools/console tab open, but I know and its bugging the $#%% out of me. How can I improve/fix this?
Upvotes: 0
Views: 1500
Reputation: 1
I am not eligible to comment that's why I have to write this answer.
The solution given is that one can use a flag to display the rows. Everything works fine with the flag added to the table data. But the problem occurs when a user sorts the table on the GUI and table is reordered.
Upvotes: -1
Reputation: 2552
You can use ng-class-odd and ng-class-even for odd and even elements in a ng-repeat cycle.
<ol>
<li ng-repeat="obj in objects">
<span ng-class-odd="'odd'" ng-class-even="'even'">
{{obj}}
</span>
</li>
</ol>
The first and all the odds will have the 'odd' class while the even will have the 'even' class.
Inside each class you can insert whatever you want as attribute.
In your case you can to something like this:
<tr ng-repeat="item in productusage | orderBy : ['RAName','PeriodStart']" ng-class-odd="'odd'" ng-class-even="'even'">
<td>{{item.RAName}}</td>
<td>{{item.ProductDescription}}</td>
<td ng-style="{'background-color': '#' + intToRGB(hashCode(item.PeriodStart)), 'color' : 'white'}">{{item.PeriodCaseCt}}</td>
<td ng-style="{'background-color': '#' + intToRGB(hashCode(item.PeriodStart)), 'color' : 'white'}">{{item.PeriodStart | date : format : shortDate}}</td>
</tr>
and the CSS would be:
.odd td{background-color:#f5f5f5}
.even td{background-color:white}
If you want instead to reach a different result please explain better what you want (maybe with a working example) and I will change my answer
Upvotes: 1
Reputation: 156
Focusing on the coloring issue, you have a few options. ng-repeat
exposes an $index
which will give you the current index of the item you're iterating upon. This is useful since you can pass it to a function on your scope, or use it directly.
<div ng-repeat="thing in things track by $index">
<div ng-style="{ 'color': $index % 2 ? 'red' : 'blue' }">{{ thing }}</div>
</div>
Or, like I said, you can use a function on the scope and pass the index to it, like so:
$scope.colorAlternate = function(index) {
var color1 = 'red'
var color2 = 'blue'
return (index % 2) ? color1 : color2;
}
Then access it in your ng-style
. You can also use ng-class
for this if you want to swap out more than just a color.
<div ng-repeat="thing in things track by $index">
<div ng-style="{ 'color': colorAlternate($index) }">{{ thing }}</div>
</div>
Edit: Adding a link to the modulo operator in case you are unfamiliar with it.
Upvotes: 1