Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make EditorFor conditionally readonly?

I have this line of code:

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

I have a variable in my view data dictionary called Readonly. How do I make Quantity read-only if ViewBag.Readonly is true and not read only if it is false?

Simple thing, but the combination of Razor with HTML (which is ancient) makes otherwise simple things impossible.

Edits:

I don't want to use an if statement. That is a last resort because it violates DRY which I have been severely burned many times in the past for not following.

The line I have above does work insofar as it makes the text box read-only. I need to make this conditional based upon my view state.

Solution:

I've used the following. It still is a DRY violation, but it reduces it to one line.

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = ViewBag.Readonly ? (object)new { @class = "form-control", @readonly = "htmlsucks" } : (object)new { @class = "form-control" } })
like image 351
Jordan Avatar asked Mar 19 '15 19:03

Jordan


People also ask

How do I add an EditorFor style?

EditorFor does not allow for styling as there are no parameters for additional attributes. The reason for this is because the EditorFor doesn't always generate a single element as it can be overridden. To style a specific type of element you need to use the specific editor you want to use.

What is EditorFor?

EditorFor<TModel,TValue>(HtmlHelper<TModel>, Expression<Func<TModel,TValue>>, String, String, Object) Returns an HTML input element for each property in the object that is represented by the expression, using the specified template, HTML field name, and additional view data.


3 Answers

EDIT: MVC 5

Controller

ViewBag.Readonly=true;//false

View

@Html.EditorFor(model => model.Quantity, ViewBag.Readonly ? (object)new { htmlAttributes = new { @readonly = "readonly", @class = "form-control" }} : new { htmlAttributes = new { @class = "form-control" } })
like image 99
ANJYR Avatar answered Oct 16 '22 10:10

ANJYR


It's very simple. Do it like this.

@if((bool)ViewBag.Readonly)
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
}
else
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })
}
like image 37
ataravati Avatar answered Oct 16 '22 11:10

ataravati


Today I had to deal with this issue as I had to dynamically set a "readonly" attribute to a Html.TextBoxFor element. I ended up writing the following helper method which allowed me to workaround the issue while keeping a DRY approach:

/// <summary>
/// Gets an object containing a htmlAttributes collection for any Razor HTML helper component,
/// supporting a static set (anonymous object) and/or a dynamic set (Dictionary)
/// </summary>
/// <param name="fixedHtmlAttributes">A fixed set of htmlAttributes (anonymous object)</param>
/// <param name="dynamicHtmlAttributes">A dynamic set of htmlAttributes (Dictionary)</param>
/// <returns>A collection of htmlAttributes including a merge of the given set(s)</returns>
public static IDictionary<string, object> GetHtmlAttributes(
    object fixedHtmlAttributes = null,
    IDictionary<string, object> dynamicHtmlAttributes = null
    )
{
    var rvd = (fixedHtmlAttributes == null)
        ? new RouteValueDictionary()
        : HtmlHelper.AnonymousObjectToHtmlAttributes(fixedHtmlAttributes);
    if (dynamicHtmlAttributes != null)
    {
        foreach (KeyValuePair<string, object> kvp in dynamicHtmlAttributes)
            rvd[kvp.Key] = kvp.Value;
    }
    return rvd;
}

It can be used in the following way:

var dic = new Dictionary<string,object>();
if (IsReadOnly()) dic.Add("readonly", "readonly");
Html.TextBoxFor(m => m.Name, GetHtmlAttributes(new { @class="someclass" }, dic))

The code is quite self-explanatory, however I also explained the underlying logic in this post on my blog.

like image 6
Darkseal Avatar answered Oct 16 '22 10:10

Darkseal