ASP.NET MVCかみそり:HTMLの条件付き属性


83

以下のコードはきれいではないようです。コードを改善するための提案はありますか?

<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

回答:


142

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 2014

3
匿名htmlPropertiesオブジェクトを渡すhtmlヘルパーを呼び出すときに同じnullを尊重する動作を実現する方法はありますか?たとえばdisabled、のように条件付きで属性を渡したいのです@Html.TextBoxFor(lambda, new { disabled = condition ? true : null })が、それでもwasのdisabled=""場合disabledはレンダリングさnullれます。これは、値に関係なく、属性が存在する場合にアクティブであるdisabled="anything"ため、レンドリングと同じdisabledです。このトピックでstackoverflow.com/q/7978137/11683が見つかりましたが、最近はもっと良い方法がありますか?
GSerg 2014年

1
サイドノート:「データ...」属性は、条件付きであること、さらにはnullを空の値をレンダリングすることはできません(stackoverflow.com/questions/13267619/...
アレクセイLevenkov

75
<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>た場合example.isNew == true、全体省略するない場合は、class属性を。


1
それを行うための非常にエレガントな方法。しかし、代わりにFunc<bool>ラムダ、私はシンプル好むでしょうbool?:それは簡単ですので、パラメータを<li @Html.Attr("class", "new", example.isNew)>
T-motyは

属性名がまだ存在している場合でも、アプリ内のカスタムJavaScriptの多くが引き続き実行されるため、このアプローチが気に入っています。そして、少なくともこれでは、属性の違いのために同じdivを繰り返すことはありません。ありがとう!
ベンスワード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.