开发者

ASP.NET MVC: How do other people apply conditional CSS classes?

开发者 https://www.devze.com 2023-04-04 19:52 出处:网络
Say I have two CSS styles called january and tuesday.I want to apply them to some text fields in my view depending on whether or not it\'s January, and Tuesday.

Say I have two CSS styles called january and tuesday. I want to apply them to some text fields in my view depending on whether or not it's January, and Tuesday.

Option A: Do the logic in the controller, and put the styles in the ViewData.

In the controller:

if( month == Month.January) 
  ViewBag.UserNameCssStyles = "january";
if( today == Day.Tuesday )
  ViewBag.UserNameCssStyles += " tuesday";

And in the view:

@Html.TextBoxFor(model => model.UserName, new { @class = ViewBag.UserNameCssStyles }

Option B: Do the logic in the controller and assign the styles in the view?

In the controller:

ViewBag.IsJanuary = (month == Month.January);
ViewBag.IsTuesday = (today == Day.Tuesday);

And in the view:

@if (ViewBag.IsJanuary && !ViewBag.IsTuesday) 
{
  @Htm开发者_高级运维l.TextBoxFor(model => model.UserName, new { @class = "january" })
}
else if (!ViewBag.IsJanuary && ViewBag.IsTuesday)
{
  @Html.TextBoxFor(model => model.UserName, new { @class = "tuesday" })
}
else if(ViewBag.IsJanuary && ViewBag.IsTuesday)
{
  @Html.TextBoxFor(model => model.UserName, new { @class = "january tuesday" })
}
else
{
  @Html.TextBoxFor(model => model.UserName)
}

Neither way seems right to me. The first option has the controller concerning itself with display, and also kind of locks up the styles so someone working on the view can't change them and, say, add a third class. But the second option seems pretty logic-heavy for being just the "dumb" view.

How do other people normally do this?


Option C: Do the logic in the controller and assign the styles in the view but in a simpler way:

In the controller:

ViewBag.IsJanuary = (month == Month.January);
ViewBag.IsTuesday = (today == Day.Tuesday);

In the view:

@string userNameClass = string.Empty;
@userNameClass += ViewBag.IsJanuary ? "january " : "";
@userNameClass += ViewBag.IsTuesday ? "tuesday " : "";

@Html.TextBoxFor(model => model.UserName, new { @class = userNameClass })

otherwise your controller is getting polluted with view concerns. An empty class is mostly harmless unless you're google and every byte counts.


Option A - definitely.

All the logic should be placed in the controller. It is controller's responsibility to pass all the necessary data to the view through the model.

Instead of multiple if statements (which is a bit of a smell) use switch or create a static dictionaries of <Month, string> and <Day, string> to store the mappings.


Have you considered using jQuery to attach the css classes? The controller should imo have no knowledge of the css class names as it breaks the separation of concerns design principle.

What you are trying to do is vary your styling based on a date, easily accomplished with jQuery so long as your are interested in the date on the client browser and not on the server where you are hosting your web site...

e.g. in your sites main .js file enter the following

$(document).ready(function () {
    var today = new Date();
    if (today.getMonth() == 0) $(".dateStyle").addClass("january");
    if (today.getDay() == 2) $(".dateStyle").addClass("tuesday");
});

Then in your view use

@Html.TextBoxFor(model => model.UserName, new { @class = "dateStyle" }

If you really need it to vary based on the date on the server, then if you want to follow this approach you will need to pass the values you have stored in your ViewBag to the javascript via a JSON object.


I know this is really old now - but I had the same kind of issue, and found all of these options to be quite ugly - especially considering that if the first condition is false, and the second is true, you'd be left with something like;

class=" className"

(note the space before the class name)

I created a HtmlHelper to resolve my issue:

public static IHtmlString ClassString(this HtmlHelper helper, Dictionary<string, bool> classes)
{
    return new HtmlString(string.Join(" ", classes.Where(c => c.Value).Select(c => c.Key)));
}

And for consitency (if a single conditional class is required):

public static IHtmlString ClassString(this HtmlHelper helper, string classString, bool condition)
{
    return new HtmlString(condition ? classString : "");
}

These can then be used as follows;

@{
    var classes = new Dictionary<string, bool>() {
        { "january", month == Month.January },
        { "tuesday", today == Day.Tuesday }
    }
}
<div class="@Html.ClassString(classes)">...</div>
// OR
@Html.TextBoxFor(model => model.UserName, new { @class = Html.ClassString(classes) })
// OR (for a single condition)
<div class="@Html.ClassString("january", month == Month.January)">...</div>
// OR
@Html.TextBoxFor(model => model.UserName, new { @class = Html.ClassString("january", month == Month.January) })
0

精彩评论

暂无评论...
验证码 换一张
取 消