99

Code below doesn't seems clean. Any suggestion to improve the code?

<li @if(ViewData["pagename"].ToString()=="Business details"){ <text>class="active" </text> } >
        <a  @if(ViewData["pagename"].ToString()=="Business details"){ <text>style="color: white; background-color: #08C; border: 1px solid #08C;" </text> }
            href="@Url.Action("BusinessDetails", "Business")">Business Details</a>
    </li> 
    <li @if (ViewData["pagename"].ToString() == "Booking policies"){ <text>class="active"</text> }> 
        <a  @if (ViewData["pagename"].ToString() == "Booking policies")
               { <text>style="color: white; background-color: #08C; border: 1px solid #08C;" </text> }
            href="@Url.Action("BookingPolicies", "Business")">Booking policies</a> 
    </li> 
Mahesh
  • 1,754
  • 7
  • 36
  • 54

8 Answers8

176

MVC has conditional attributes built in. For example:

<div @{if (myClass != null) { <text>class="@myClass"</text> } }>Content</div>
<div class="@myClass">Content</div>

If @myClass is null, it just won't use the attribute at all.

I know that may not quite solve your current issue, but it is noteworthy!

See also: John Galloway's blog post on ASP.NET MVC 4 Beta > Conditional attribute rendering

KyleMit
  • 30,350
  • 66
  • 462
  • 664
jcreamer898
  • 8,109
  • 5
  • 41
  • 56
  • Be careful that your class name isn't 'active' or you'll have an entry class attribute. No idea why. – ScottE Aug 06 '14 at 19:34
  • 4
    Is there a way to achieve same null-respecting behaviour when calling to html helpers passing the anonymous `htmlProperties` object? E.g. I want to conditionally pass attribute `disabled`, like `@Html.TextBoxFor(lambda, new { disabled = condition ? true : null })`, but that still renders `disabled=""` when `disabled` was `null`, which is the same as rendring `disabled="anything"` because `disabled` is active when the attribute is present, regardless of the value. Found http://stackoverflow.com/q/7978137/11683 on the topic, but are there better ways nowadays I wonder? – GSerg Oct 14 '14 at 14:35
  • 6
    Side note: "data-..." attributes can't be conditional and render empty value even for null (http://stackoverflow.com/questions/13267619/razor-conditional-attribute-not-working) – Alexei Levenkov Jan 24 '17 at 20:32
  • Damn! Didn't know this until now :-) – Mabakay Apr 15 '21 at 13:01
  • @GSerg Try using `@Html.TextBoxFor(lambda, condition ? new { disabled = true } : null)`; that's what I typically do for HTML Helpers. The caveat is I believe it has to either be an object or null to work (ie. you can't use two anonymous objects with one property removed as one result). – Pluto Nov 15 '21 at 20:48
85
<li class="@(ViewBag.pagename == "Business details" ? "active" : null)">  

You should replace the inline style="..." with a separate classname and use the same syntax there.

However, it would be cleaner to make a separate HTML helper extension method that takes a page and action name and generates the HTML generically.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
24

I use a small helper method that will conditionally add an attribute if the value is non-empty, and, if defined, when a Boolean function expression evaluates to true:

public static MvcHtmlString Attr(this HtmlHelper helper, string name, string value, Func<bool> condition = null)
{
    if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value))
    {
        return MvcHtmlString.Empty;
    }

    var render = condition != null ? condition() : true;

    return render ? 
        new MvcHtmlString(string.Format("{0}=\"{1}\"", name, HttpUtility.HtmlAttributeEncode(value))) : 
        MvcHtmlString.Empty;
}

Once defined, I can use this method in my Razor views:

<li @(Html.Attr("class", "new", () => example.isNew))>
...
</li>

The above code will render <li class="new">...</li> if example.isNew == true, if not will omit the entire class attribute.

defrost
  • 396
  • 2
  • 6
  • 1
    Very elegant way for do that. But instead of `Func` lambda, i will prefer a simple `bool?` parameter, because it's simpler: `
  • `
  • – T-moty Dec 08 '16 at 18:16
  • I like this approach because a lot of the custom JavaScript in my app will still run when the attribute name is still there. And at least this doesn't make you repeat the same div because of attribute differences. Thanks! – Ben Sewards Apr 10 '17 at 15:30