ASP.NET MVCのEditorFor()のHTML属性


129

なぜHTML属性をに渡せないのEditorFor()ですか?例えば;

<%= Html.EditorFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", readonly = "readonly" }) %>

メタデータを使いたくない

更新:解決策はビューからこれを呼び出すことでした:

 <%=Html.EditorFor( model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>

そしてViewData["Modifiable"]、カスタムのEditorTemplates / String.ascxで使用します。入力に読み取り専用属性または無効属性を追加するかどうかを決定するビューロジックがあります。渡される匿名オブジェクトはEditorFor()呼び出されるパラメーターでadditionalViewDataあり、そのプロパティはエディターテンプレートに渡されます。ViewDataコレクション。


19
真剣に、まだMVC3でこの制限は意味がなく、本当に迷惑です。世界中の人々が時間を費やし、このナンセンスで髪を抜いています。これをMicrosoft Connectに送信します。
JuniorMayhé2012


3
それは私だけですか、それとも、すごく単純なはずの何かに対して多くのbsのように思われますか?
エリックK

多分これはあなたを助ける:[1] [1] [CSSクラスとHTML属性を持つEditorFor-実装]:stackoverflow.com/questions/12675708/...
FunThom

回答:


96

EditorForメタデータで動作するので、html属性を追加したい場合はいつでもできます。別のオプションは、単にカスタムテンプレートを記述して使用することTextBoxForです。

<%= Html.TextBoxFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", @readonly = "readonly" }) %>    

html属性はモデルの他のプロパティによって異なるため、メタデータは機能しません。つまり、ドメインまたはviemodelロジックは、静的メタデータではなくhtml属性を決定する必要があります。または、要点を逃しているのですが、メタデータを動的に設定できますか?
Typo Johnson

なにPeriodType?単純なプロパティではないですか?それは複雑なオブジェクトである場合は、部分的で配置することによって、全体のテンプレートをカスタマイズすることができ可能性の型名であるプロパティを。~/Views/ControllerName/EditorTemplates/SomeType.ascxSomeTypePeriodType
Darin Dimitrov

また、提案されたコードは、モデル全体を特定のプロパティにアクセスする部分テンプレートに渡すことを意味します。これは、各プロパティに部分があることを意味しますか?
Typo Johnson

2
私は今あなたをつかまえます。<%= Html.EditorFor(model => model.Control.PeriodEndDate、new {Modifiable = model.Control.PeriodEndDateModifiable})%>を使用して、カスタムEditorTemplates / String.ascxでViewData ["PeriodEndDateModifiable"]を使用できます。ありがとう
Typo Johnson

1
@JuniorMayhé、私はこれを退屈な制限とは言いません。もっとよく考えれば、これが理にかなっていることを理解できるでしょう。実際、EditorForヘルパーの要点は、対応するテンプレートを持つことができるということです。このテンプレートには、任意のマークアップを含めることができます。必ずしも単一の要素ではありません。@classたとえば、3つのdivを含むエディターテンプレートを定義してもまったく意味がありません。Html.TextBoxForヘルパーを使用すると、これを定義できます。これは、このヘルパーが生成するものを知っているためです。テキストボックスなので、入力要素にクラスを定義するのが理にかなっています。
Darin Dimitrov 2012

115

更新 MVC 5.1は、以下のアプローチを直接サポートするようになったため、組み込みエディターでも機能します。http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features (同じように考えている偉大なマインドの場合か、私の答えを読んだ場合:)

更新を終了

独自のエディターテンプレートを使用している場合、またはMVC 5.1を使用している場合は、組み込みエディターに対して直接以下のアプローチをサポートします。

@Html.EditorFor(modelItem => item.YourProperty, 
  new { htmlAttributes = new { @class="verificationStatusSelect", style = "Width:50px"  } })

その後、テンプレートで(MVC 5.1の単純型には不要)

@Html.TextBoxFor(m => m, ViewData["htmlAttributes"])

5
この新機能は、4年前に尋ねられた元の問題を完全に解決します。
CoderSteve 2014年

1
TextBoxForとそのようなヘルパーの代わりに、大量のカスタムエディターテンプレートを使用する場合、ViewData [...]をそれぞれに追加することは素晴らしいアイデアとは言えません... :(
Alexander

42

MVC 5.1以降、次のことができるようになりました。

@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })

http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features


上記のリンクは死んでいます。これはMVC 5.1で利用できます。詳細はこちら:asp.net/mvc/overview/releases/mvc51-release-notes#new-features
Alaa Masoud

1
おかげで、リンクも修正しました。
vtforester 2014

2
htmlAttributesをマージする方法
Bart Calixto 2014

これは、組み込みの/デフォルトEditorForテンプレートでのみ機能します。独自に実装する場合は、AntonKの回答に従う必要があります。
mxmissile

6

ASP.Net MVC 5.1はそれのためのサポートが組み込まれました。

リリースノートから

EditorForでHTML属性を匿名オブジェクトとして渡すことができるようになりました。

例えば:

@Html.EditorFor(model => model, 
              new { htmlAttributes = new { @class = "form-control" }, })

4

MVC 5.1 EditorForのHTML属性のVB.Netコード構文は次のとおりです

@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))

3

なぜ使用しないのか

@Html.DisplayFor(model => model.Control.PeriodType)

30
1つの理由は、DisplayForが入力をレンダリングしないため、値がポストバックで失われるためです。
ProfK 2012

2
もう1つの理由は、エディターが現在ロックされているが常にロックされていないという特定のシナリオであり、データが編集可能であることを伝えたい場合-今だけではありません。
ミール

2

メタデータを使用したくない場合は、[UIHint("PeriodType")]属性を使用してプロパティを装飾できます。または、複合型の場合は、何も装飾する必要はありません。EditorForは、EditorTemplatesフォルダーでPeriodType.aspxまたはascxファイルを探し、代わりにそれを使用します。


おかげで、私のエディターテンプレートのif / elseが特定のフィールドでのみ必要な場合は、結局それを行う可能性があります
Typo Johnson

私はあなたがあなたのモデル(あなたのコードではない)を変えることができないと言ったので、UIHintで直接装飾することはオプションではありませんでした。
ダレルリー

2

私は今日、nullable boolにバインドするチェックボックスについて同じ問題に取り組んできました。モデル(コードではない)を変更できないため、これを処理するより良い方法を考え出す必要がありました。それは少し強引ですが、私が遭遇する可能性のあるケースの99%で機能するはずです。入力タイプごとに有効な属性を手動で入力する必要があることは明らかですが、チェックボックスにはそれらをすべて取得したと思います。

私のBoolean.cshtmlエディターテンプレート:

@model bool?

@{
    var attribs = new Dictionary<string, object>();
    var validAttribs = new string[] {"style", "class", "checked", "@class",
        "classname","id", "required", "value", "disabled", "readonly", 
        "accesskey", "lang", "tabindex", "title", "onblur", "onfocus", 
        "onclick", "onchange", "ondblclick", "onmousedown", "onmousemove", 
        "onmouseout", "onmouseover", "onmouseup", "onselect"};
    foreach (var item in ViewData) 
    {
        if (item.Key.ToLower().IndexOf("data_") == 0 || item.Key.ToLower().IndexOf("aria_") == 0) 
        {
            attribs.Add(item.Key.Replace('_', '-'), item.Value);
        } 
        else 
        {
            if (validAttribs.Contains(item.Key.ToLower()))
            {
                attribs.Add(item.Key, item.Value);
            }
        }
    }
}

@Html.CheckBox("", Model.GetValueOrDefault(), attribs)

追加Dictionary<string,string> attribs = new Dictionary<string,string>();し、ページの上部にあるブロックのattribs.Add("tabindex","16");1つに追加しました@( )。次に@Html.CheckBox("IsActive", Model.IsActive.HasValue ? Model.IsActive : false, attribs)、自分のページで実行すると、エラーが発生します。「 'System.Web.Mvc.HtmlHelper <MyProject.Models.MyObject>'には、 'CheckBox'の定義が含まれておらず、最適な拡張メソッドオーバーロード 'System.Web。 Mvc.InputExtensions.CheckBox(System.Web.Mvc.HtmlHelper、string.bool、object) 'に無効な引数があります。
vapcguy 2014年

2

EditorForは引き続き使用できます。スタイル/どちらのhtml属性もViewDataとして渡すだけです。

@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" })

EditorForはテンプレートを使用してレンダリングするため、プロパティのデフォルトテンプレートをオーバーライドして、style属性をViewDataとして単に渡すことができます。

したがって、EditorTemplateは次のようになります。

@inherits System.Web.Mvc.WebViewPage<object>

@Html.TextBoxFor(m => m, new { @class = "text ui-widget-content", style=ViewData["style"] })

1
Html.TextBoxFor(model => model.Control.PeriodType, 
    new { @class="text-box single-line"})

このように使用できます。と同じ出力でHtml.EditorFor、html属性を追加できます


ただし、適用しようとしている可能性のあるTextBoxForタイプはすべて無視さDisplayFormatれます。
エリックK

1

Views / Shared / EditorTemplates / MyTypeEditor.vbhtmlにタイプの独自のテンプレートを作成するだけです

@ModelType MyType

@ModelType MyType
@Code
    Dim name As String = ViewData("ControlId")
    If String.IsNullOrEmpty(name) Then
        name = "MyTypeEditor"
    End If
End Code

' Mark-up for MyType Editor
@Html.TextBox(name, Model, New With {.style = "width:65px;background-color:yellow"})

モデルプロパティを使用してビューからエディターを呼び出します。

@Html.EditorFor(Function(m) m.MyTypeProperty, "MyTypeEditor", New {.ControlId = "uniqueId"})

VB構文を許してください。それがまさに私たちが転がる方法です。


1

私の場合、追加の属性を受け取ることができるHTML5数値入力エディターテンプレートを作成しようとしていました。きちんとしたアプローチは独自のHTMLヘルパーを作成することですが、私はすでに.ascxテンプレートを持っているので、このアプローチを採用しました。

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input id="<%= Regex.Replace(ViewData.TemplateInfo.GetFullHtmlFieldId(""), @"[\[\]]", "_") %>" name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>" type="number" value="<%= ViewData.TemplateInfo.FormattedModelValue %>"
<% if (ViewData["attributes"] != null)
   {
       Dictionary<string, string> attributes = (Dictionary<string, string>)ViewData["attributes"];
       foreach (string attributeName in attributes.Keys){%>
        <%= String.Format(" {0}=\"{1}\"", attributeName, attributes[attributeName])%>
       <% }
   } %> />

この醜いビットは、数値タイプの入力を作成し、キー「属性」を持つViewDataディクショナリを探します。これは、キーと値のペアを属性として追加して、ディクショナリを反復処理します。ID属性のRegexは無関係であり、コレクションで使用した場合、通常はアンダースコアとしてエスケープされるGetFullHtmlFieldId()角かっこ[]を含むIDを返すため、存在します。

次に、このテンプレートは次のように呼び出されます。

Html.EditorFor(m => m.Quantity, "NumberField", new { attributes = new Dictionary<string, string>() { { "class", "txtQuantity" } } }

冗長ですが、機能します。テンプレートでリフレクションを使用して、辞書を使用する代わりにプロパティ名を属性名として使用することもできます。


1

ViewDataコントローラーで条件を設定

ViewData["Modifiable"] = model.recProcessed;

次に、このビューデータをエディターテンプレートで使用して、コントロールのhtml属性を設定します。

@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new  { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })

0

MVC 5.1以降のソリューション(ローカルのHtmlAttributeをマージし、EditorTemplatesで定義します):

Shared \ EditorTemplates \ String.cshtml:

@Html.TextBoxFor(model => model, new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark }.ToExpando().MergeHtmlAttributes(ViewData["htmlAttributes"].ToExpando()))

拡張:

public static IDictionary<string, object> MergeHtmlAttributes(this ExpandoObject source1, dynamic source2)
{
    Condition.Requires(source1, "source1").IsNotNull().IsLongerThan(0);

    IDictionary<string, object> result = source2 == null
        ? new Dictionary<string, object>()
        : (IDictionary<string, object>) source2;

    var dictionary1 = (IDictionary<string, object>) source1;

    string[] commonKeys = result.Keys.Where(dictionary1.ContainsKey).ToArray();
    foreach (var key in commonKeys)
    {
        result[key] = string.Format("{0} {1}", dictionary1[key], result[key]);
    }

    foreach (var item in dictionary1.Where(pair => !result.ContainsKey(pair.Key)))
    {
        result.Add(item);
    }

    return result;
}

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (var item in anonymousDictionary)
        expando.Add(item);
    return (ExpandoObject)expando;
}

public static bool HasProperty(this ExpandoObject expando, string key)
{
    return ((IDictionary<string, object>)expando).ContainsKey(key);
}

使用法:

@Html.EditorFor(m => m.PromotionalCode, new { htmlAttributes = new { ng_model = "roomCtrl.searchRoomModel().promoCode" }})

1
ありがとう、うまくいきました。すべてのdata_xxx属性を除いて、私は_を- source1および-にキャストするときにに置き換える必要がありsource2ましたIDictionary<string, object>。私はこの機能を作りました: private static IDictionary<string, object> ToHtmlAttributesDictionary(this IEnumerable<KeyValuePair<string, object>> dico) { return dico.ToDictionary(s => s.Key.Replace('_', '-'), s => s.Value); }
Marien Monnier 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.