Odd/Even Looping in ASP.NET MVC
Ran into a post from Steve Sandersen earlier in which he laments the verbosity of doing things like odd/even parsing in an iterative loop in ASP.NET MVC. Steve proceeds to show an abstract solution which is a great idea for more complex scenarios, but if all you need is odd even type parsing may be a bit of overkill especially since it such a common scenario.
I tend to use a slightly simpler approach for odd even figuring based on a logical variable that’s changed in a loop. Here’s what my version of similar code looks like:
<% bool oddEven = true; foreach (CodeSnippetListItem snip in snippetList) { %> <div class="<%= (oddEven = !oddEven) ? "evenclass" : "oddclass" %>"> Content goes here... </div> <% } %>
That’s not too bad to read as far as tag soup goes. The key is a logical var that is simple ‘not-ed’ – this can be done after the { or as I’ve done here direclty inline of the expression. The only hard part with this code is figuring out whether it starts on odd or even :-}
Another option is to use some client script code – jQuery can make short work of applying classes after the page’s been loaded.
<script type="text/javascript"> $(document).ready(function() { $(".snippet:odd").addClass("listalternate"); }); </script>
Given the two approaches I think the former is the better choice because I like to keep the display at the point where it’s applied in the HTML or style sheet and just in case JavaScript doesn’t work the display is consistent either way.
Options are good though…
Other Posts you might also like
The Voices of Reason
# re: Odd/Even Looping in ASP.NET MVC
This approach (GetRowClass that explicitly hardcodes the class names for odd and even) takes a view feature - the CSS class name - and puts it in code which to me is all wrong. The view should be changeable by a designer without having to look into a separate code file.
While I'm no big fan of tag soup I think many folks are overreacting to keeping the view clean of code. By removing display elements and even display logic out of the view into helpers or other support methods you're actually making the flow of the page harder to read, understand and most importantly modify.
# re: Odd/Even Looping in ASP.NET MVC
Overboard? Funny when I read this I fired up LiveWriter and started to write "Why Rick Needs a Helper Enema" but then thought to myself - wait a minute, I've written this stuff before and found the post that mottey referenced.
So Rick - I love you man but listen, you need to "get into the groove" a bit before dissing me :). In this case, there are many helpers that you can use/reuse and encapsulate. This kind of thing:
<%= (oddEven = !oddEven) ? "evenclass" : "oddclass" %>
Is just not cool my man. The whole idea of DRY is that you don't want that exact thing all over your views (it's repetitious, crunchy, and if you change your mind... well you get it).
Helpers terse-up the View and make "slinging" the HTML/View logic easier. You used to give me a hard time about the lack of components - well this kind of thing underscores that pain. Some discipline here will help you - I promise!
# re: Odd/Even Looping in ASP.NET MVC
Next you're going to tell me you don't like <%= Bite.Me %> as an expression either, huh?:-}
# re: Odd/Even Looping in ASP.NET MVC
#foreach(...)
#beforeall
...
#afterall
...
#odd
...
#even
...
#nodata
...
#each
...
#end# re: Odd/Even Looping in ASP.NET MVC
<div each="var snip in snippetList" class="oddclass?{snipIndex % 2 == 0} evenclass?{snipIndex % 2 != 0}"> Content goes here </div>
And you can push it into a parametrised partial if you want reuse to make Rob happy. Cut the markup out, rename the collection to something suitably generic, name the partial _AlternatingDivs and you can call it using:
<AlternatingDivs items="snippetList"/>
Look ma, no HtmlHelpers. Spark partials and macros eliminate much of the need for them.
# re: Odd/Even Looping in ASP.NET MVC
# re: Odd/Even Looping in ASP.NET MVC
How much friction is created when css class names change? Probably not something that happens that often but someone will have to touch all the <%= (oddEven = !oddEven) ? "evenclass" : "oddclass" %> throughout a project.
How would you handle First, Last, Interior, etc?
Maybe a better solution would be to overload Steve's CssClass(string prefix){...} with
CssClass(string even, string odd){...} and
CssClass(string even, string odd, string first, string last, string interior){...}
Not as scalable but still allows the css class names to be defined within the view.
# re: Odd/Even Looping in ASP.NET MVC
More Spark advertising. Spark iteration defines variables IsFirst,isLast,Index and Count. So you can do:
<div each="item in collection" class="first?{itemIsFirst} last?{itemIsLast}"> Item ${itemIndex} of ${itemCount} </div>
It's almost like the guys who work on it do web programming for a living.
# re: Odd/Even Looping in ASP.NET MVC
I guess I'm stuck in my ways but personally I don't see the need to create an alternate syntax for views when all these alternate syntaxes are doing is approximating the code anyway in a different and non-familiar way. To me this smells of another layer of abstraction and another 'language' you have to learn and track and maintain (and new developers) - to me this feels like more hassle than it's worth. Given everything code is the most flexible way to do anything you need even if it might be more verbose.
Sometimes it really feels to me that people take form over function a bit to far (memories of discussion with Rob re: REST formatting comes to mind too) :-}
# re: Odd/Even Looping in ASP.NET MVC
We're abstracting away a lot of html with helpers already so it kinda seems like a natural progression.
# re: Odd/Even Looping in ASP.NET MVC
Then again this is just my gut feeling and for all I know is this may be completely off base, but I'm against abstracting too much logic into little tiny morsels that you have to hunt down all over the place in code. To be honest I've not had enough time with MVC at this point to make any judgement calls even for my own code let alone for making suggestions to others :-}.
# re: Odd/Even Looping in ASP.NET MVC
I don't see any utility in replacing 1 line of simple code with a helper. It's adding unnecessary coupling and polluting the rest of the code.
But, uf you're going to go mad and code one anyways, instead of a static helper, at least create a simple class that does it for you.
e.g.
<% var altRow = new AltRow("oddclass", "evenclass"); foreach (CodeSnippetListItem snip in snippetList) { %> <div class="<%= altRow.Row() %>"> Content goes here... </div> <% } %>
and the AltRow is trivially easy, but at least the state and behavior is refactored away, and also doesn't depend on an index. I think many people missed the fact that Rick wasn't iterating using a for loop.
class AltRow { private string oddClass; private string evenClass private bool isOdd = false; public AltRow(string oddClass, string evenClass) { ... } public string Row() { isOdd = !isOdd; return isOdd ? oddClass : evenClass; } }
# re: Odd/Even Looping in ASP.NET MVC
# re: Odd/Even Looping in ASP.NET MVC
I would prefer a:
public class Alternator<T> { public Alternator(T odd, T even); public T Next(); }
That would allow me alternate any other values on my templates.
Anyway, I don't find much sense in the "and if you change your mind..." Rob comment, really, how often would you change your mind about this expression:
<%= (oddEven = !oddEven) ? "evenclass" : "oddclass" %>
it's just an "odd/even" snippet.
by the way, Rick, is there code colouring for this Asp.Net with includes?
# re: Odd/Even Looping in ASP.NET MVC
Having worked on heavy JavaScript/AJAX sites we quickly learnt that the convenience of using jQuery to add alt row classes wasnt worth the (albeit minimal) client-side performance hit.