How to concisely create optional HTML attributes with razor view engine?

后端 未结 8 920
鱼传尺愫
鱼传尺愫 2020-12-23 16:51

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

相关标签:
8条回答
  • 2020-12-23 17:01

    class attribute would not be rendered by Razor if value is null

    <a href="#nolink" class="@(categoryId == null ? "submenu-active": null)">All</a>
    
    0 讨论(0)
  • 2020-12-23 17:03

    I've come up with a chainable HtmlAttribute class and some Html Extension methods to allow the Razor syntax below:

    <ul> 
        @foreach (var mi in items) { 
        <li @Html.Css("selected", mi.Selected)> 
            <a href="@mi.Href" @Html.Attr("title", mi.Title)>@mi.Text</a> 
        </li> 
        } 
    </ul> 
    

    Here is the HtmlAttribute class:

    public class HtmlAttribute : IHtmlString     
    {
        private string _InternalValue = String.Empty;
        private string _Seperator;
    
        public string Name { get; set; }
        public string Value { get; set; }
        public bool Condition { get; set; }
    
        public HtmlAttribute(string name)
            : this(name, null)
        {
        }
    
        public HtmlAttribute( string name, string seperator )
        {
            Name = name;
            _Seperator = seperator ?? " ";
        }
    
        public HtmlAttribute Add(string value)
        {
            return Add(value, true);
        }
    
        public HtmlAttribute Add(string value, bool condition)
        {
            if (!String.IsNullOrWhiteSpace(value) && condition)
                _InternalValue += value + _Seperator;
    
            return this;
        }
    
        public string ToHtmlString()
        {
            if (!String.IsNullOrWhiteSpace(_InternalValue))
                _InternalValue = String.Format("{0}=\"{1}\"", Name, _InternalValue.Substring(0, _InternalValue.Length - _Seperator.Length));
            return _InternalValue;
        }
    }
    

    Extra info: The "seperator" is used to chain together multiple values for an attribute. This can be useful for multiple css class names (use a space) or perhaps use String.Empty to build an value dependant on multiple conditions (by using the .Add() method)

    And here are the Html Extension helper methods:

    public static class Extensions
    {
        public static HtmlAttribute Css(this HtmlHelper html, string value)
        {
            return Css(html, value, true);
        }
    
        public static HtmlAttribute Css(this HtmlHelper html, string value, bool condition)
        {
            return Css(html, null, value, condition);
        }
    
        public static HtmlAttribute Css(this HtmlHelper html, string seperator, string value, bool condition)
        {
            return new HtmlAttribute("class", seperator).Add(value, condition);
        }
    
        public static HtmlAttribute Attr(this HtmlHelper html, string name, string value)
        {
            return Attr(html, name, value, true);
        }
    
        public static HtmlAttribute Attr(this HtmlHelper html, string name, string value, bool condition)
        {
            return Attr(html, name, null, value, condition);
        }
    
        public static HtmlAttribute Attr(this HtmlHelper html, string name, string seperator, string value, bool condition)
        {
            return new HtmlAttribute(name, seperator).Add(value, condition);
        }
    }
    

    Let me know if they are of use.

    Thanks,

    Lee

    0 讨论(0)
  • 2020-12-23 17:04

    For the case of multiple classes I use this simple extension method:

    public static MvcHtmlString If(this string text, bool condition) {
        return new MvcHtmlString(condition ? text : string.Empty);
    }
    

    And in the view:

    <div class="menuitem @("active".If(Model.Active))">
    
    0 讨论(0)
  • 2020-12-23 17:10
    <ul>
    @foreach (var mi in Model.MenuItems) {
      <li@(Html.Raw((mi.Selected ? " class=\"selected\"" : null))>
        <a href="@mi.Href">@mi.Text</a>
      </li>
    }
    </ul>
    
    0 讨论(0)
  • 2020-12-23 17:11

    It's really pretty simple and clean:

    <p @(cssClass != null) ? { class="@cssClass" }> Stuff and whatnot... </p>
    
    0 讨论(0)
  • 2020-12-23 17:12

    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>
    
    0 讨论(0)
提交回复
热议问题