ASP.NET MVC Razor : HTML의 조건부 속성


84

아래 코드는 깨끗하지 않은 것 같습니다. 코드를 개선하기위한 제안이 있습니까?

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

아마도 하위 링크 요소로 LI를 렌더링하는 사용자 정의 HTML 도우미를 만들 수 있습니까?
Nick Bork

답변:


146

MVC에는 조건부 속성이 내장되어 있습니다.

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

@myClass가 null이면 속성을 전혀 사용하지 않습니다.

현재 문제를 해결하지 못할 수도 있지만 주목할 만합니다!

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


클래스 이름이 '활성'이 아니거나 항목 클래스 속성이 있는지주의하십시오. 이유를 모르겠습니다.
ScottE

3
익명 htmlProperties객체를 전달하는 HTML 도우미를 호출 할 때 동일한 null 존중 동작을 달성하는 방법이 있습니까? 예 I 조건부 속성을 전달할 disabled@Html.TextBoxFor(lambda, new { disabled = condition ? true : null })하지만 여전히 렌더링 disabled=""disabled였다 nullrendring 같은 인 disabled="anything"때문에 disabled특성에 상관없이 값에있을 때 활성이다. 주제에 대해 stackoverflow.com/q/7978137/11683 을 찾았 지만 요즘 더 나은 방법이 있습니까?
GSerg 2014 년

1
사이드 노트 : "데이터가 ..."속성은 조건이 될 수없고 (심지어 널 (null)에 대한 빈 값을 렌더링 stackoverflow.com/questions/13267619/... )
알렉세이 Levenkov

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

인라인 style="..."을 별도의 클래스 이름으로 바꾸고 동일한 구문을 사용해야합니다.

그러나 페이지 및 작업 이름을 가져와 일반적으로 HTML을 생성하는 별도의 HTML 도우미 확장 메서드를 만드는 것이 더 깔끔합니다.


1
다른 옵션 (Razor 2.0 옵션 외에)보다 훨씬 깔끔한 좋은 것입니다.
ctrlplusb 2013 년

21

값이 비어 있지 않은 경우 조건부로 속성을 추가하고 정의 된 경우 부울 함수식이 다음과 같이 평가 될 때 속성을 추가하는 작은 도우미 메서드를 사용합니다 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;
}

정의되면 Razor 뷰에서이 메서드를 사용할 수 있습니다.

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

위의 코드는 <li class="new">...</li>if example.isNew == true, 그렇지 않으면 전체 class속성 을 생략 합니다.


1
그렇게하기위한 매우 우아한 방법입니다. 하지만 Func<bool>람다 대신 간단한 bool?매개 변수 를 선호합니다 . 더 간단합니다.<li @Html.Attr("class", "new", example.isNew)>
T-moty

이 접근 방식을 좋아하는 이유는 속성 이름이 아직있을 때 내 앱의 많은 사용자 지정 JavaScript가 계속 실행되기 때문입니다. 그리고 적어도 이것은 속성 차이로 인해 동일한 div를 반복하지 않습니다. 감사!
Ben Sewards 2017


0

TagWrap 확장 방법으로 접근합니다. 질문에 대한 코드는 다음과 같습니다.

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

TagWrap 확장 방법

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()));
}

Dispose에서 닫는 태그를 렌더링하는 데 사용되는 도우미 클래스

public class DisposableAction : IDisposable
{
    private readonly Action DisposeAction;

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

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

0

제상을 기반으로 여기에 적응, object대신 다음을 사용합니다 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;
    }

이렇게하면 다른 데이터 유형을 전달하기 전에 문자열로 변환 할 필요가 없습니다 .ToString(). 차이점 이 있습니다. 빈 문자열을 전달해 도 여전히 렌더링됩니다. 예를 들면 :

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

// Ouput:
data-foo=""

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

그런 다음 HTML에서

<li @Html.Raw(classAttr) >  
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.