ASP.NET MVC dao cạo: thuộc tính điều kiện trong HTML


83

Mã bên dưới có vẻ không sạch. Bất kỳ đề xuất để cải thiện mã?

<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> 

Có lẽ việc tạo một trình trợ giúp HTML tùy chỉnh sẽ hiển thị LI với các phần tử liên kết con?
Nick Bork

Câu trả lời:


142

MVC có các thuộc tính điều kiện được xây dựng trong ...

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

Nếu @myClass là null, nó sẽ không sử dụng thuộc tính nào cả ...

Tôi biết rằng điều đó có thể không hoàn toàn giải quyết được vấn đề hiện tại của bạn, nhưng nó đáng chú ý!

http://weblogs.asp.net/jgalloway/archive/2012/02/16/asp-net-4-beta-released.aspx


Hãy cẩn thận rằng tên lớp của bạn không 'hoạt động' hoặc bạn sẽ có thuộc tính lớp mục nhập. Không biết tại sao.
ScottE

3
Có cách nào để đạt được hành vi tôn trọng không khi gọi đến trình trợ giúp html chuyển htmlPropertiesđối tượng ẩn danh không? Ví dụ như tôi muốn có điều kiện vượt qua thuộc tính disabled, giống như @Html.TextBoxFor(lambda, new { disabled = condition ? true : null }), nhưng điều đó vẫn làm cho disabled=""khi disabledđã null, mà là giống như rendring disabled="anything"disabledlà hoạt động khi thuộc tính là hiện nay, không phụ thuộc vào giá trị. Tìm thấy stackoverflow.com/q/7978137/11683 trên chủ đề này, nhưng tôi tự hỏi hiện nay có cách nào tốt hơn không?
GSerg

1
Lưu ý phụ: "Dữ liệu -..." thuộc tính không thể có điều kiện và đưa ra giá trị rỗng ngay cả đối với null ( stackoverflow.com/questions/13267619/... )
Alexei Levenkov

75
<li class="@(ViewBag.pagename == "Business details" ? "active" : null)">  

Bạn nên thay thế nội dòng style="..."bằng một tên lớp riêng biệt và sử dụng cùng một cú pháp ở đó.

Tuy nhiên, sẽ dễ dàng hơn nếu tạo một phương thức mở rộng trình trợ giúp HTML riêng biệt lấy một trang và tên hành động và tạo HTML một cách chung chung.


1
Đẹp, sạch hơn nhiều so với một số tùy chọn khác (ngoài tùy chọn Razor 2.0).
ctrlplusb

21

Tôi sử dụng một phương thức trợ giúp nhỏ sẽ thêm một thuộc tính có điều kiện nếu giá trị không trống và, nếu được định nghĩa, khi một biểu thức hàm Boolean đánh giá thành 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;
}

Sau khi xác định, tôi có thể sử dụng phương pháp này trong các khung nhìn Razor của mình:

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

Đoạn mã trên sẽ hiển thị <li class="new">...</li>nếu example.isNew == true, nếu không sẽ bỏ qua toàn bộ classthuộc tính.


1
Cách rất thanh lịch để làm điều đó. Nhưng thay vì Func<bool>lambda, tôi sẽ thích một cách đơn giản bool?thông số, vì nó đơn giản:<li @Html.Attr("class", "new", example.isNew)>
T-moty

Tôi thích cách tiếp cận này vì nhiều JavaScript tùy chỉnh trong ứng dụng của tôi sẽ vẫn chạy khi tên thuộc tính vẫn ở đó. Và ít nhất điều này không khiến bạn lặp lại cùng một div vì sự khác biệt về thuộc tính. Cảm ơn!
Ben Sewards


0

Tiếp cận với phương pháp mở rộng TagWrap. Mã cho câu hỏi của bạn sẽ giống như sau:

@using (Html.TagWrap("li", condition ? new { @class = "active" } : null))
{
    var anchorAttrs = new Dictionary<string, object> { { "href", Url.Action("BusinessDetails", "Business") } };
    if(condition)
    {
        anchorAttrs["style"] = "color: white; background-color: #08C; border: 1px solid #08C;";
    }
    using (Html.TagWrap("a", anchorAttrs))
    {
        <text>Business Details</text>
    }
}

Các phương pháp mở rộng TagWrap

sử dụng Microsoft.AspNetCore.Mvc.ViewFeatures;

public static IDisposable TagWrap(this IHtmlHelper htmlHelper, string tagName, object data)
{
    return htmlHelper.TagWrap(tagName, HtmlHelper.AnonymousObjectToHtmlAttributes(data));
}

public static IDisposable TagWrap(this IHtmlHelper htmlHelper, string tagName, IDictionary<string, object> data)
{
    var tag = new TagBuilder(tagName);
    tag.MergeAttributes(data);

    htmlHelper.ViewContext.Writer.Write(tag.RenderStartTag());

    return new DisposableAction(() =>
        htmlHelper.ViewContext.Writer.Write(tag.RenderEndTag()));
}

Lớp người trợ giúp được sử dụng để hiển thị thẻ đóng trên Dispose

public class DisposableAction : IDisposable
{
    private readonly Action DisposeAction;

    public DisposableAction(Action action)
    {
        DisposeAction = action;
    }

    public void Dispose()
    {
        DisposeAction();
    }
}

0

Dựa trên câu trả lời về rã đông ở đây là một sự thích nghi, objectthay vì một string:

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

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

        return render ? 
            new MvcHtmlString($"{attributeName}=\"{HttpUtility.HtmlAttributeEncode(value.ToString())}\"") : 
            MvcHtmlString.Empty;
    }

Bằng cách này, bạn không phải chuyển các kiểu dữ liệu khác của mình thành các chuỗi trước khi chuyển chúng, tiết kiệm một lượng nhỏ .ToString(). Có một sự khác biệt là : truyền một chuỗi rỗng sẽ vẫn hiển thị. Ví dụ như:

@Html.ConditionalAttr("data-foo", "", () => Model.IsFooNeeded)

// Ouput:
data-foo=""

0
@{ var classAttr= needClass ? "class=\"class-name\"" : "" }

và sau đó trong HTML

<li @Html.Raw(classAttr) >  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.