Question

I have a strongly-typed MVC View Control which is responsible for the UI where users can create and edit Client items. I'd like them to be able to define the ClientId on creation, but not edit, and this to be reflected in the UI.

To this end, I have the following line:

<%= Html.TextBox("Client.ClientId", ViewData.Model.ClientId, new 
 { @readonly = 
   (ViewData.Model.ClientId != null && ViewData.Model.ClientId.Length > 0 
      ? "readonly" : "false") 
 } )
%>

It seems that no matter what value I give the readonly attribute (even "false" and ""), Firefox and IE7 make the input read-only, which is annoyingly counter-intuitive. Is there a nice, ternary-operator-based way to drop the attribute completely if it is not required?

Was it helpful?

Solution

Tough problem... However, if you want to define only the readonly attribute, you can do it like this:

<%= Html.TextBox("Client.ClientId", ViewData.Model.ClientId, 
  ViewData.Model.ClientId != null && ViewData.Model.ClientId.Length > 0 
    ? new { @readonly =  "readonly" } 
    : null) 
%>

If you want to define more attributes then you must define two anonymous types and have multiple copies of the attributes. For example, something like this (which I don't like anyway):

ClientId.Length > 0 
  ? (object)new { @readonly = "readonly", @class = "myCSS" } 
  : (object)new { @class = "myCSS" }

OTHER TIPS

If you want to define several attributes, and conditional readonly without duplicate the other attributes, you can use Dictionary instead of anonymous types for the attributes.

e.g.

Dictionary<string, object> htmlAttributes = new Dictionary<string, object>();
htmlAttributes.Add("class", "myCSS");
htmlAttributes.Add("data-attr1", "val1");
htmlAttributes.Add("data-attr2", "val2");
if (Model.LoggedInData.IsAdmin == false)
{
    htmlAttributes.Add("readonly", "readonly");
}


@:User: @Html.TextBoxFor(
    m => m.User,
    htmlAttributes)  

And alternative is just to emit it as plain old HTML. Yes, the editor will make you think you are wrong, but that seems to happen quite frequently with VS2008SP1. This example is specifically for checkboxes which seems to be completely wasted in CTP5, but it gives you an idea how to emit conditional attributes.

<input type="checkbox" name="roles" value='<%# Eval("Name") %>' 
  <%# ((bool) Eval("InRole")) ? "checked" : "" %> 
  <%# ViewData.Model.IsInRole("Admin") ? "" : "disabled" %> />

Tip: Its the mere presence of readonly/disabled attribute that makes the element readonly or disabled in the browser.

@Html.TextBoxFor(x => x.Name, isReadonly ?(object) new { @readonly = true } : new { /*Some other attributes*/ })

I think it should be

<%= ((bool) Eval("InRole")) ? "checked" : "" %> 

instead of this in leppies answer.

<%# ((bool) Eval("InRole")) ? "checked" : "" %> 

At least it did not work for me with # but it worked with =. Did i do anything wrong? Thanks for the tip anyway :)

$(function() { $("[readonly='false']").removeAttr("readonly"); });

i use this :

   @Html.TextAreaFor(model => model.ComentarioGestor, comentarioGestor? new { @class = "form-control" } : new { @class = "form-control", @readonly = "readonly" } as object)

I tried most of the suggestions above and now I have arrived at the simplest with a single line. Combine 2 anonymous html attributes object by declaring wither one of it as "object" type.

@Html.TextBoxFor(m => m.Email, !isEdit ? new { id = "email_box" } : new { id = "email_box", @readonly = isEdit ? "readonly" : "false" } as object)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top