views:

114

answers:

3

I'm looking for a way to write the following code with less lines of code (maybe 5). I suppose I could do the same thing as the selected class but this razor syntax isn't looking pretty.

<ul>
@foreach (var mi in Model.MenuItems) {
  <li@(mi.Selected?" class=\"selected\"":null)>
  @if (string.IsNullOrEmpty(mi.Title)) {
    <a href="@mi.Href">@mi.Text</a>
  } else {
    <a href="@mi.Href" title="@mi.Title">@mi.Text</a>
  }
  </li>
}
</ul>
+1  A: 

Ditch Razor and use Spark view engine. ;)

See how much simpiler optional HTML attributes work here http://sparkviewengine.com/documentation/expressions#Conditionalattributeoutput

Daveo
+2  A: 
<ul>
@foreach (var mi in Model.MenuItems) {
    <li@(mi.Selected?" class=\"selected\"":null)>
        <a href="@mi.Href" @{if(!string.IsNullOrEmpty(mi.Title)) { <text>title="@mi.Title"</text>} }>@mi.Text</a>
    </li>
}
</ul>

I haven't tested it but it parses correctly.

BuildStarted
This does not work
JarrettV
Wow, had you taken the time too look at the error message you would have seen that all you needed to do was add a {} around the if block contents and you would have seen my code produces the exact output you were looking for...
BuildStarted
Yikes, I did "look" at the error message and tried the brackets but I must not have comprehended the message. :) Thanks for updating your post.
JarrettV
Sorry, I know it came off as rude. Bad morning. That said, I would definitely look at Darin's html helper since that was MVC is basically all about.
BuildStarted
+3  A: 

That would be a good candidate for custom HTML helper:

public static class HtmlExtensions
{
    public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, MenuItem mi)
    {
        var li = new TagBuilder("li");
        if (mi.Selected)
        {
            li.AddCssClass("selected");
        }
        var a = new TagBuilder("a");
        a.MergeAttribute("href", mi.Href);
        if (!string.IsNullOrEmpty(mi.Title))
        {
            a.MergeAttribute("title", mi.Title);
        }
        a.SetInnerText(mi.Text);
        return MvcHtmlString.Create(li.ToString());
    }
}

and in your view:

<ul>
@foreach (var mi in Model.MenuItems) {
    @Html.MenuItem(mi)
}
</ul>

or using DisplayTemplates you don't even need to write a loop:

<ul>
    @Html.DisplayFor(x => x.MenuItems)
</ul>
Darin Dimitrov
Darin, your code is great but somehow I feel like this is defeating the purpose of razor. Microsoft needs to address this.
JarrettV