views:

2419

answers:

3

hey guys,
Lately, I'v been struggling with an annoying situation on ASP.NET MVC. Here's the story in short,
I'm supposed to have a view that lists all of the products; now because those products are too many, I'm paging them (very innovative heh!). The page contains two paging arrows -"Next 10 products", "and previous 10 products". The view is passed a IEnumerable<Product> collection containing the list of products to be displayed. The view is also passed two integers (currentPage, totalPages) as ViewData items. Now what I need to accomplish is to check if it's the first page (ViewData["CurrentPage"] == 0) I should change the css class of the "previous 10 pages" link to disabled, so I came up with something like the following

 <a href="/Products/Page<%=Html.Encode(Convert.ToInt32(ViewData["CurrentPage"])-1)%>/" 
           class="<%=Convert.ToInt32(ViewData["CurrentPage"]) <= 1 ? "bgn disabled" : ""%>">                          
                previous 10 products                
        </a>

This worked fine, still there's a problem. Though the link is disabled, or specifically grayed, it still points to a valid URL, so I tried to actually change the href attribute of the link based on the CurrentPage variable. Here's how the code looks like (get ready to the pure ugliness):

<a href="<%=Convert.ToInt32(ViewData["CurrentPage"]) <= 0 ? 
        "javascript:void[]" : 
        "/products/Page<%=Html.Encode(Convert.ToInt32(ViewData["CurrentPage"])+1)%>/" %>" 
        class="<%=Convert.ToInt32(ViewData["CurrentPage"]) <= 0 ? 
        "bgn disabled" :
        ""%>">

    previous 10 products
    </a>

Now, my problems with this code are:

  1. The second statement doesn't work, apparently because of the nested server side scripts
  2. It's very ugly, and absolutely unreadable (imagine I'm doing this with each page that requires paging! pain in the but). :(

Any better alternatives guys?

+3  A: 

You can use an if statement:

<% if (Convert.ToInt32(ViewData["CurrentPage"]) <= 0) { %>
     Disabled template goes here...
<% } else { %> 
     Link template goes here...
<% } %>

By the way, if you're doing this for a set of pages, you can encapsulate it in a ViewUserControl or a ViewMasterPage.

Mehrdad Afshari
Well, getting red of the ternary operator really helped. It looks better now, but, isn't there any other approach to refactor this even more?
Galilyou
Beside the encapsulation in a control or master page, I suggest using a strongly typed model rather than using `ViewData` directly. Other than that, you could build your own HTML helper too, if that makes sense.
Mehrdad Afshari
A: 
omoto
Well, actually I'm trying to have only two links [previous 10, and next 10]. I'm not sure if your pager helper method can help with that. Thanks though.
Galilyou
Welcome, no problem :_)
omoto
+1  A: 

Here is another solution. Add <script runat="server">:

<script runat="server">
    protected string Prev10Url {
        get {
            return Convert.ToInt32(ViewData["CurrentPage"]) <= 0
                ? "javascript:void[]"
                : "/products/Page" + Html.Encode(Convert.ToInt32(ViewData["CurrentPage"])+1);
        }
    }

    protected string Prev10Class {
        get {
            return Convert.ToInt32(ViewData["CurrentPage"]) <= 0
                ? "bgn disabled"
                : "";
        }
    }

    protected string Next10Url {
        get {
            ...
        }
    }

    protected string Next10Class {
        get {
            ...
        }
    }
</script>

And then change your markup:

<a href="<%= Prev10Url %>" class="<%= Prev10Class %>">previous 10 products</a>
<a href="<%= Next10Url %>" class="<%= Next10Class %>">next 10 products</a>
eu-ge-ne
+1 cleaner than the mess I came up with anyways :)
Galilyou