MVC3 EditorFor readOnly
Asked Answered
H

12

73

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.

Hoeve answered 11/4, 2012 at 15:33 Comment(4)
If it's a read-only, then it's no longer an editor. It should probably by DisplayForIntestinal
Making an editor readonly kind of defeats the object of it. Why not just use DisplayFor?Terebinthine
possible duplicate of how do i set disabled attribute on html textbox in asp.net-mvc?Cerelly
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.Faustino
A
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" })
Adjoining answered 11/4, 2012 at 18:13 Comment(3)
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: msdn.microsoft.com/en-us/library/ee834942(v=vs.100).aspxTracheostomy
@Tracheostomy 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.Adjoining
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" } }).Cancroid
H
35

This code is supported in MVC4 onwards

@Html.EditorFor(model => model.userName, new { htmlAttributes = new { @class = "form-control", disabled = "disabled", @readonly = "readonly" } })
Homunculus answered 13/11, 2015 at 17:12 Comment(3)
The key change is to wrap the html attributes in the "new { htmlAttributes =" <your desired attributes> "}" strings. This appears to be unique pattern for the EditorFor (different that DisplayFor, DropdownFor, etc.)Faustino
I agree with Matthew LockHomunculus
Thing worth mentioning is that disabled elements won't be passed into the Controller. If you'd like to pass it, use readonlyLanky
T
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

Tyro answered 17/5, 2013 at 16:14 Comment(3)
Thank you Seichi! This is the real solution to the exact problem!Speos
This is a great answer. It describes what the original question is valid, as well as actually answering the OP. Great job!Paulin
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 !!!Lost
B
6

You can do it this way:

@Html.EditorFor(m => m.userName, new { htmlAttributes = new { disabled = true } })
Brindabrindell answered 31/8, 2016 at 7:2 Comment(1)
I finally found a solution in MVC 4, Thanks!!Biebel
T
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 = "" } })
Timepiece answered 13/4, 2016 at 23:35 Comment(0)
S
4

Try using:

@Html.DisplayFor(model => model.userName) <br/>
@Html.HiddenFor(model => model.userName)
Sarilda answered 4/5, 2016 at 10:22 Comment(0)
D
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.

Dampen answered 4/11, 2013 at 23:45 Comment(0)
F
2

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" } })
 }
Ferrule answered 6/4, 2019 at 11:32 Comment(1)
Thanks for formatting Litisqe Kumar - i'd forgotten how to do it.Ferrule
F
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; }
Fascista answered 5/8, 2013 at 17:12 Comment(0)
E
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" } })
Evania answered 5/10, 2016 at 16:11 Comment(0)
L
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>
Longfellow answered 20/8, 2014 at 19:32 Comment(0)
P
-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; }
    }
Pectase answered 17/1, 2014 at 9:1 Comment(2)
adding [Editable(false)] doesn't seem to do anything to make the control readonlyFrustule
you should also extend InputTagHelper as I explained in my answer here: https://mcmap.net/q/272226/-mvc3-editorfor-readonlyInhalator

© 2022 - 2024 — McMap. All rights reserved.