72

I want to make readOnly with EditorFor in edit page.

I tried to put readonly and disabled as:

<div class="editor-field">
        @Html.EditorFor(model => model.userName, new { disabled = "disabled", @readonly = "readonly" })
    </div>

However, it does not work. How can I make to disable edit this field?

Thank you.

wholee1
  • 1,491
  • 13
  • 34
  • 51
  • 7
    If it's a read-only, then it's no longer an editor. It should probably by DisplayFor –  Apr 11 '12 at 15:34
  • 5
    Making an editor readonly kind of defeats the object of it. Why not just use DisplayFor? – ChrisBint Apr 11 '12 at 15:34
  • 2
    possible duplicate of [how do i set disabled attribute on html textbox in asp.net-mvc?](http://stackoverflow.com/questions/3443460/how-do-i-set-disabled-attribute-on-html-textbox-in-asp-net-mvc) – Kyle Trauberman Apr 11 '12 at 15:40
  • 3
    The reason one may wish to do user EditorFor (but disabled) is appearance, That is my reason. DisplayFor creates a text output without enclosing box and has to be CSS adjusted to line up on the form correctly (not difficult, just some padding-top). But you may want to have a form with all fields in boxes, with ReadOnly values say grayed out. – Greg Terrell Jul 14 '16 at 11:23

12 Answers12

104

The EditorFor html helper does not have overloads that take HTML attributes. In this case, you need to use something more specific like TextBoxFor:

<div class="editor-field">
    @Html.TextBoxFor(model => model.userName, new 
        { disabled = "disabled", @readonly = "readonly" })
</div>

You can still use EditorFor, but you will need to have a TextBoxFor in a custom EditorTemplate:

public class MyModel
{
    [UIHint("userName")]
    public string userName { ;get; set; }
}

Then, in your Views/Shared/EditorTemplates folder, create a file userName.cshtml. In that file, put this:

@model string
@Html.TextBoxFor(m => m, new { disabled = "disabled", @readonly = "readonly" })
danludwig
  • 46,965
  • 25
  • 159
  • 237
  • I can't find the overloads that allow to specify arguments. Is there another extension method I've missed? Can't find it with Intellisense, neither find it in the msdn docs: http://msdn.microsoft.com/en-us/library/ee834942(v=vs.100).aspx – JotaBe Apr 19 '13 at 16:15
  • @JotaBe I think you are right, but I thought I saw these before. Perhaps it was in MVC4 pre-releases, or perhaps I imagined it. Either way, I have updated the answer. – danludwig Apr 19 '13 at 18:20
  • 4
    In the newer versions of MVC (I believe 4+ ?) the `additionalViewData` object can have `htmlAttributes` property which `EditorFor` and the like use for html attributes. So it will become: `@Html.EditorFor(model => model.userName, new { htmlAttributes = new { disabled = "disabled", @readonly = "readonly" } })`. – GSerg Sep 06 '15 at 17:15
35

This code is supported in MVC4 onwards

@Html.EditorFor(model => model.userName, new { htmlAttributes = new { @class = "form-control", disabled = "disabled", @readonly = "readonly" } })
Vitani
  • 1,594
  • 1
  • 14
  • 28
  • 1
    The key change is to wrap the html attributes in the "new { htmlAttributes =" "}" strings. This appears to be unique pattern for the EditorFor (different that DisplayFor, DropdownFor, etc.) – Greg Terrell Jul 14 '16 at 11:31
  • I agree with Matthew Lock – GSoft Consulting May 25 '19 at 23:10
  • 1
    Thing worth mentioning is that ```disabled``` elements won't be passed into the Controller. If you'd like to pass it, use ```readonly``` – Duck Ling May 02 '20 at 16:23
13

For those who wonder why you want to use an EditoFor if you don`t want it to be editable, I have an example.

I have this in my Model.

    [DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0: dd/MM/yyyy}")]
    public DateTime issueDate { get; set; }

and when you want to display that format, the only way it works is with an EditorFor, but I have a jquery datepicker for that "input" so it has to be readonly to avoid the users of writting down wrong dates.

To make it work the way I want I put this in the View...

     @Html.EditorFor(m => m.issueDate, new{ @class="inp", @style="width:200px", @MaxLength = "200"})

and this in my ready function...

     $('#issueDate').prop('readOnly', true);

I hope this would be helpful for someone out there. Sorry for my English

Seichi
  • 273
  • 4
  • 11
  • Thank you Seichi! This is the real solution to the exact problem! – Ivo Stoyanov Feb 09 '15 at 14:50
  • This is a great answer. It describes what the original question is valid, as well as actually answering the OP. Great job! – Rob10e Jan 15 '16 at 19:54
  • Simple straight forward answer thank you very much! Requirements had me jumping back and forth while reviewing a defect I realized my change to editorfor allowed my desired DisplayFormating but I discovered they were no longer read only this was a great find !!! – ChristianProgrammer Mar 15 '16 at 13:26
6

You can do it this way:

@Html.EditorFor(m => m.userName, new { htmlAttributes = new { disabled = true } })
Francois
  • 131
  • 1
  • 4
5

I know the question states MVC 3, but it was 2012, so just in case:

As of MVC 5.1 you can now pass HTML attributes to EditorFor like so:

@Html.EditorFor(x => x.Name, new { htmlAttributes = new { @readonly = "", disabled = "" } })
stovroz
  • 6,835
  • 2
  • 48
  • 59
4

Try using:

@Html.DisplayFor(model => model.userName) <br/>
@Html.HiddenFor(model => model.userName)
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
3

Here's how I do it:

Model:

[ReadOnly(true)]
public string Email { get { return DbUser.Email; } }

View:

@Html.TheEditorFor(x => x.Email)

Extension:

namespace System.Web.Mvc
{
    public static class CustomExtensions
    {
        public static MvcHtmlString TheEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
        {
            return iEREditorForInternal(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        private static MvcHtmlString iEREditorForInternal<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            if (htmlAttributes == null) htmlAttributes = new Dictionary<string, object>();

            TagBuilder builder = new TagBuilder("div");
            builder.MergeAttributes(htmlAttributes);

            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);


            string labelHtml = labelHtml = Html.LabelExtensions.LabelFor(htmlHelper, expression).ToHtmlString();

            if (metadata.IsRequired)
                labelHtml = Html.LabelExtensions.LabelFor(htmlHelper, expression, new { @class = "required" }).ToHtmlString();


            string editorHtml = Html.EditorExtensions.EditorFor(htmlHelper, expression).ToHtmlString();

            if (metadata.IsReadOnly)
                editorHtml = Html.DisplayExtensions.DisplayFor(htmlHelper, expression).ToHtmlString();


            string validationHtml = Html.ValidationExtensions.ValidationMessageFor(htmlHelper, expression).ToHtmlString();

            builder.InnerHtml = labelHtml + editorHtml + validationHtml;

            return new MvcHtmlString(builder.ToString(TagRenderMode.Normal));
        }
    }
}

Of course my editor is doing a bunch more stuff, like adding a label, adding a required class to that label as necessary, adding a DisplayFor if the property is ReadOnly EditorFor if its not, adding a ValidateMessageFor and finally wrapping all of that in a Div that can have Html Attributes assigned to it... my Views are super clean.

Serj Sagan
  • 28,927
  • 17
  • 154
  • 183
1

Create an EditorTemplate for a specific set of Views (bound by one Controller): enter image description here

In this example I have a template for a Date, but you can change it to whatever you want.

Here is the code in the Data.cshtml:

@model Nullable<DateTime>

@Html.TextBox("", @Model != null ? String.Format("{0:d}",     ((System.DateTime)Model).ToShortDateString()) : "", new { @class = "datefield", type =    "date", disabled = "disabled"  @readonly = "readonly" }) 

and in the model:

[DataType(DataType.Date)]
public DateTime? BlahDate { get; set; }
DaniilZ
  • 51
  • 1
1

Old post I know.. but now you can do this to keep alignment and all looking consistent..

 @Html.EditorFor(model => model.myField, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
da_jokker
  • 954
  • 2
  • 12
  • 16
1

I use the readonly attribute instead of disabled attribute - as this will still submit the value when the field is readonly.

Note: Any presence of the readonly attribute will make the field readonly even if set to false, so hence why I branch the editor for code like below.

 @if (disabled)
 {
     @Html.EditorFor(model => contact.EmailAddress, new { htmlAttributes = new { @class = "form-control", @readonly = "" } })
 }
 else
 {
     @Html.EditorFor(model => contact.EmailAddress, new { htmlAttributes = new { @class = "form-control" } })
 }
Litisqe Kumar
  • 2,512
  • 4
  • 26
  • 40
john blair
  • 466
  • 5
  • 13
0
<div class="editor-field">
        @Html.EditorFor(model => model.userName)
</div>

Use jquery to disable

<script type="text/javascript">
   $(document).ready(function () {
      $('#userName').attr('disabled', true);
     });
</script>
Luís Ponciano
  • 157
  • 1
  • 5
-1

i think this is simple than other by using [Editable(false)] attribute

for example:

 public class MyModel
    {
        [Editable(false)]
        public string userName { get; set; }
    }
MaTya
  • 782
  • 6
  • 11