2012-10-18 10 views
9

Voglio poter visualizzare del testo, ma anche il testo essere modificabile tramite jQuery.MVC3 Html.DisplayFor - È possibile che questo controllo generi un ID?

<%= Html.DisplayFor(model => model.DeviceComponentName)%> 

Se ho usato EditorFor invece di DisplayFor, vedrei un ID per il controllo di input. Non voglio che il valore sia modificabile in quel modo, però. Quindi, l'ho reso un DisplayFor, ma non genera una proprietà ID per l'elemento.

devo solo avvolgere la DisplayFor in un div e fare qualcosa di simile:

<div id="<%= ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") %>"> 
    <%= Html.DisplayFor(model => model.DeviceComponentName)%> 
</div> 

$('#DeviceComponentName').text('newValue'); 

O c'è un modo più pulito per raggiungere tale obiettivo?

Aggiornamento: C'è un modo che non dipende da stringhe codificate? Qualcosa che si lega all'oggetto stesso, quindi se il nome della mia proprietà cambia, otterrei un errore di compilazione?

Inoltre, io sto usando questo codice, ma non vedo un valore ID appaiono:

<td class="editableValue"> 
    <%--Label should be editable, so it needs an ID, but only will be edited by jQuery so it can't be an EditorFor--%> 
    <%= Html.DisplayFor(model => model.DeviceComponentName, new { id = "DeviceComponentName" })%> 
    <button type="button" id="ComponentTreeButton" class="nestedDialogButton">...</button> 
</td> 

risposta

18

Per evitare ingressi 'stringa magica' (nel caso in cui le proprietà modello cambiano), si potrebbe fare questo con un'estensione. E 'anche per il codice molto più pulito:

public static MvcHtmlString DisplayWithIdFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string wrapperTag = "div") 
{ 
    var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression)); 
    return MvcHtmlString.Create(string.Format("<{0} id=\"{1}\">{2}</{0}>", wrapperTag, id, helper.DisplayFor(expression))); 
} 

Poi è sufficiente utilizzare in questo modo:

@Html.DisplayWithIdFor(x => x.Name) 

produrrà

<div id="Name">Bill</div> 

Oppure, se si vuole che essere avvolto in un arco:

@Html.DisplayWithIdFor(x => x.Name, "span") 

Quale farà:

<span id="Name">Bill</span> 

non Razor

Per la sintassi non rasoio, è sufficiente utilizzare in questo modo:

<%= Html.DisplayWithIdFor(x => x.Name) %> 

e:

<%= Html.DisplayWithIdFor(x => x.Name, "span") %> 
+0

Aggiunta la sintassi del non-rasoio - il codice stesso rimane lo stesso. – naspinski

+2

La sintassi del non-rasoio dovrebbe avere il carattere @ prima dell'Html? –

+1

hai ragione Sean: P modificato – naspinski

5

è necessario essere l'uso:

Html.DisplayFor(model => model.DeviceComponentName, new { @id = "DeviceComponentName"}) 

Per id dinamica e altre proprietà, io uso :

Classe per i metadati:

public class AdditionalHtml : Attribute, IMetadataAware 
{ 
    public string Id { get; set; } 

    public string Type { get; set; } 

    public string CssClass { get; set; } 

    public string PlaceHolder { get; set; } 

    public string Style { get; set; } 

    public string OnChange { get; set; } 

    public int Rows { get; set; } 

    public int MaxLength { get; set; } 

    public bool ReadOnly { get; set; } 

    public bool Disabled { get; set; } 

    public Dictionary<string, object> OptionalAttributes() 
    { 
     var options = new Dictionary<string, object>(); 

     if (!string.IsNullOrWhiteSpace(Id)) 
      options.Add("id", Id); 

     if (!string.IsNullOrWhiteSpace(Type)) 
      options.Add("type", Type); 

     if (!string.IsNullOrWhiteSpace(CssClass)) 
      options.Add("class", CssClass); 

     if (!string.IsNullOrWhiteSpace(PlaceHolder)) 
      options.Add("placeholder", PlaceHolder); 

     if (!string.IsNullOrWhiteSpace(OnChange)) 
      options.Add("onchange", OnChange); 

     if (!string.IsNullOrWhiteSpace(Style)) 
      options.Add("style", Style); 

     if (Rows != 0) 
      options.Add("rows", Rows); 

     if (MaxLength != 0) 
      options.Add("maxlength", MaxLength); 

     if (ReadOnly) 
      options.Add("readonly", "readonly"); 

     if (Disabled) 
      options.Add("disabled", "disabled"); 

     return options; 
    } 

classe per il provider di metadati:

public class MetadataProvider : DataAnnotationsModelMetadataProvider 
{ 
    protected override ModelMetadata CreateMetadata (IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) 
    { 
     var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 

     var additionalHtmlValues = attributes.OfType<AdditionalHtml>().FirstOrDefault(); 

     if (additionalHtmlValues != null) 
     { 
      metadata.AdditionalValues.Add("AdditionalHtml", additionalHtmlValues); 
     } 

     return metadata; 
    } 
} 

Add aiutante:

public static class HtmlAttributesHelper 
{ 
    public static string GetHtmlAttribute<T> (this T model, Expression<Func<T, object>> expression, string attribName) 
    { 
     string strDefault = String.Empty; 
     MemberInfo member = null; 

     switch (expression.Body.NodeType) 
     { 
      case ExpressionType.Lambda: 
      case ExpressionType.Convert: 
       { 
        var body = expression.Body as UnaryExpression; 
        if (body == null) 
         return strDefault; 
        var operand = body.Operand as MemberExpression; 
        if (operand == null) 
         return strDefault; 
        member = operand.Member; 
        break; 
       } 
      case ExpressionType.MemberAccess: 
       { 
        var body = expression.Body as MemberExpression; 
        if (body == null) 
         return strDefault; 
        member = body.Member; 
        break; 
       } 
      default: 
       { 
        return expression.Body.ToString() + " " + expression.Body.NodeType.ToString(); 
       } 
     } 

     if (member == null) 
      return strDefault; 

     var attr = member.GetCustomAttributes(typeof(AdditionalHtml), false); 
     if (attr.Length > 0) 
     { 
      return (attr [ 0 ] as AdditionalHtml).OptionalAttributes() [ attribName.ToLower() ].ToString(); 
     } 

     // Return Name of Property if AdditionalHtml.Id is empty 
     return attribName == "Id" ? member.Name : strDefault; 
    } 

    public static string GetHtmlId<T> (this T model, Expression<Func<T, object>> expression) 
    { 
     return model.GetHtmlAttribute(expression, "Id"); 
    } 
} 

fornitore di registro in Global.ASax:

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     //.... 
     ModelMetadataProviders.Current = new MetadataProvider(); 
    } 

nel modello u possibile utilizzare AdditionHtml come come:

[AdditionalHtml(Id = "OrderNo", CssClass = ShortTextStyle, Disabled = true)] 
    public string OrderNo { get; set; } 

e ora è possibile utilizzare sintassi per js (in vista):

$('#@Model.GetHtmlId(x => x.PropertyName)') 

E in vista, è possibile utilizzare:

@Html.DisplayFor(x => x.FormDate) 

Attributi HTML a tached automaticamente

+1

C'è un modo per essere dinamico? Cosa succede se il nome della mia proprietà cambia? –

+2

@SeanAnderson yes youcan utilizzare ViewBag o ViewData per passare il valore id dal controller '@ Html.DisplayFor (model => model.DeviceComponentName, new {id = ViewBag.DeviceComponentID})' –

2

HtmlHelpers hanno le sostituzioni che permettono di passare in un oggetto, o un dizionario, per aggiungere attributi al tag html generato:

@Html.DisplayFor(model => model.DeviceComponentName, new { id = "myId" }) 

@Html.DisplayFor(model => model.DeviceComponentName, new Dictionary<string, object>() { { "id", "myId" } }) 

o

@Html.DisplayFor(model => model.DeviceComponentName, new { id = ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") }) 

@Html.DisplayFor(model => model.DeviceComponentName, new Dictionary<string, object>() { { "id", ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName" } }) 

UPDATE:

Dopo aver esaminato il codice aggiornato e riletto la domanda, ecco cosa suggerirei - che è simile a la tua prima idea

<td class="editableValue" id="<%= ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") %>"> 
    <%= Html.DisplayFor(model => model.DeviceComponentName)%> 
    <button type="button" id="ComponentTreeButton" class="nestedDialogButton">...</button> 
</td> 

Non dovrebbe essere necessario aggiungere un extra div all'interno del TD, perché è possibile modificare il valore all'interno del td direttamente tramite il jQuery. Credo che il seguente dovrebbe raggiungere questo obiettivo:

$('#DeviceComponentName').html('newValue'); 
+0

Non sto usando la sintassi di Razor, ma non visualizzo un ID quando uso uno degli esempi. Modificherò nel post superiore ciò che ho provato. –

3

Basta aggiungere un HiddenFor al di sopra della colonna. Questo ti darà un ID da usare per quello che ti serve. Semplice e fa il trucco per te per afferrare quel valore per ID.

<%= Html.HiddenFor(model => model.DeviceComponentName)%> 
<%= Html.DisplayFor(model => model.DeviceComponentName)%> 
1

Noi non possono creare id per Displayfor() controllo rasoio .. Possiamo usare controllo HTML come etichetta dello span invece di Displayfor) di controllo (. Altrimenti possiamo mettere display per controllo in span control. ora possiamo creare id per estensione. questo il modo in cui abbiamo a che fare ..

esempio <sapn id="spanid">@Html.Displayfor(modelItem => item.id) </sapn>

0

Ecco soluzione naspinski con la possibilità di aggiungere htmlAttributes.

public static MvcHtmlString DisplayWithIdFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string wrapperTag = "div") 
    { 
     var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression)); 

     if (htmlAttributes != null) 
     { 
      var tag = new TagBuilder(wrapperTag); 
      tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) as IDictionary<string, object>); 
      tag.Attributes.Add("id", id); 
      tag.SetInnerText(helper.DisplayFor(expression).ToHtmlString()); 

      return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal)); 
     } 
     else 
     { 
      return MvcHtmlString.Create(string.Format("<{0} id=\"{1}\">{2}</{0}>", wrapperTag, id, helper.DisplayFor(expression))); 
     } 
    } 
0

La soluzione più semplice per me era utilizzare una casella di testo di sola lettura. @ Html.TextBoxFor (u => u.Visibilidade, new {disabled = "disabled"})

Problemi correlati