简体   繁体   中英

Set property “readonly” for @Html.TextBoxFor( ) dynamically based on fetched information from db

I have multiple Textboxes defined using @Html.TextBoxFor(). Now I want some of them to be only "readonly" and some of them editable, based on the role of user accessing the page.

I have tried using the following

@Html.TextBoxFor(f => f.VSSLabel, new { style = "height:19px", @Value = @ViewBag.fetchf.VSSLabel, @readonly="readonly" })

Is there any way that we can set @readonly="false" and it becomes editable, or any other approach so I switch it to "readonly" and editable based on the Value stored in a ViewBag variable coming from controller?

Unfortunately all the below mark will render a readonly textbox input

<input type="text" name="s1" readonly="readonly"/>
<input type="text" name="s2" readonly="no" />
<input type="text" name="s2" readonly="reallyDoNotWant" />
<input type="text" name="s3" readonly="false" />
<input type="text" name="s4" readonly />

The existence of readonly attribute makes the input element readonly. Value does not matter.

So you should conditionally render it

if (yourExpressionWhichGivesBooleanValue)
{
    @Html.TextBoxFor(a => a.VSSLabel)
}
else
{
    @Html.TextBoxFor(a => a.VSSLabel, new { @readonly = "readonly" })
}

If you want to check it against a viewbag dictionary item

if (ViewBag.IsAdmin !=null && ViewBag.IsAdmin)
{
    @Html.TextBoxFor(a => a.VSSLabel)
}
else
{
    @Html.TextBoxFor(a => a.VSSLabel, new { @readonly = "readonly" })
}

Assuming you are setting ViewBag.IsAdmin to a boolean value in your action method.

What Shyju's says is true, however Shariq Ali is correct that if you have lots of fields to do the Razor code gets quite inefficient.

In my case I have an entire form that I want to make read-only in certain cases. One of the ways I discovered to do that solves your question with a little less coding.

@{
object htmlAttr = null;

if ( ViewBag.AllowEdit != null && !ViewBag.AllowEdit ){
    htmlAttr = new { @class="CSS", @readonly="readonly"};
}
else {
    htmlAttr = new { @class="CSS" };
}

@Html.TextBoxFor( m => m.Field, htmlAttr)

Since most edit controls in a form carry the same CSS class this should take care of most of the need. If you find that you need more classes on some controls simply add additional htmlAttribute objects to carry the different class configs.

By using descriptive variable names this centralizes the logic for readonly and makes your razor page more concise.

To make your code easier to read you can use function which you can declare:

@functions
{
    private object GetAttributes()
    {
        if (ViewBag.IsAdmin !=null && ViewBag.IsAdmin)
        {
            return null;
        }

        return new { @readonly = "readonly" };
    }
}

and then you can use it like this:

@Html.TextBoxFor(a => a.VSSLabel, GetAttributes())

In function you can add any attributes you need to add to an element:

return new { @class = "form-control", @readonly = "readonly", @required = "required" }

and it works perfectly

You could write an extension method like this:

/* for .NET Core       */ using Microsoft.AspNetCore.Mvc.ViewFeatures;
/* for .NET Framework: */ using System.Web.WebPages.Html;

public static class HtmlHelpers
{
    public static object MakeReadonly(this object htmlAttributes, bool isReadonly)
    {
        if (isReadonly)
        {
            var dynamicHtmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            dynamicHtmlAttributes["readonly"] = "readonly";
            return dynamicHtmlAttributes;
        }

        return htmlAttributes;
    }
}

Usage:

@Html.TextBoxFor(..., new { @class = "form-control" }.MakeReadonly(true))

One disadvantage of this approach is, that extension methods on object are a bit questionable since they'll pop up everywhere in IntelliSense.

If you don' like this, I'd suggest changing the htmlAttributes from an anonymous object to a ViewDataDictionary and make the extension method working with that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM