10

I want to conditionally render a readonly attribute in an <input>. In the ASP.NET Core dialect of Razor the interpretation of attributes is a little different opposed to System.Web.Mvc.

In System.Web.Mvc I used to do:

<input name="Name" class="form-control" @(Model.MyCondition ? "readonly" : "") />

In ASP.NET Core, the same does not work: no error, but the attribute isn't rendered either.

<input asp-for="Name" class="form-control" @(Model.MyCondition ? "readonly" : "" ) />

Once the attribute is present in the HTML it is enforced, so I cannot do something with the value of the attribute. This snippet would cause the input to always be read-only:

<input asp-for="Name" class="form-control" readonly="@(Model.MyCondition ? "readonly" : "" )" />

Now, I can work around by creating a tag helper that would respond to the is-readonly tag, but that seems very convoluted for something so simple.

How do I conditionally render a no-value attribute without resorting to a custom tag helper?

Sebazzz
  • 1,205
  • 2
  • 15
  • 33
  • I test in razor page it works on my side , when MyCondition is true it shows the `readonly` attribute , could you please share the steps to reproduce ? – Nan Yu Apr 25 '19 at 06:20
  • Here's [a link](https://stackoverflow.com/a/71665997/5480409) to an answer of mine that solves the same problem, just omit the value part. – Francesco B. Mar 30 '22 at 07:06

3 Answers3

13

If you set the value to null when your condition isn't matched (instead of an empty string) then the attribute will not be rendered, as follows:

<input asp-for="Name" class="form-control" readonly="@(Model.MyCondition ? "readonly" : null )" />
SpruceMoose
  • 9,737
  • 4
  • 39
  • 53
  • 10
    This does not seem to work for me. It still renders the "readonly" attribute without a value – Ryan D May 27 '19 at 02:41
  • Look at this: https://stackoverflow.com/questions/9399531/asp-net-mvc-razor-conditional-attribute-in-html – Perseus Jul 25 '19 at 19:05
  • 1
    This definitely works for me with ASP.NET Core 3.1; I even inspected the raw source to confirm. That said, I was using the `disabled` value instead of `readonly` (but they should work the same). I was also using the `asp-for` attribute, if that makes any difference. – Pluto Nov 13 '21 at 18:35
  • 1
    @Pluto This is strange because any `attribute="@(nullValuedVariable)"` renders `attribute=""` for me in .net core 3.1 mvc. – Feri Nov 15 '21 at 10:36
  • @Feri I wonder if it has to do with Razor compiling the page and only programming the behavior to skip outputting the attribute if there's an explicit null check. Did you try using a conditional expression instead of only outputting the variable? There's got to be some reason for this inconsistent behavior. I know doing `@(obj == null ? null : obj)` is stupid, but with ASP.NET it just might work LOL – Pluto Nov 15 '21 at 20:50
  • this worked perfect in .net core 7 + MVC thx! – d0rf47 Apr 04 '23 at 17:59
0
@{
    var htmlAttributes = (MyModel.MyCondition == true) ? (object)new
    {
        @@readonly = "readonly"
    } : null;
}

@Html.TextBoxFor(m => m.Nom,  htmlAttributes)
Romain
  • 1
  • 2
-1

What I do is create an @if statement. I find it more transparent.

@if (Model.MyCondition)
{
  <input asp-for="Name" class="form-control" readonly="readonly" />
}
else
{
  <input asp-for="Name" class="form-control" />
}
Adrián Alvarez
  • 329
  • 3
  • 10
  • I get you got downvoted because this doesn't answer the question exactly, but this is a simple way to accomplish what I needed and I was blinded by trying to force conditional attributes to be the solution like other front-end frameworks support when ASPNET Razor never had that feature as a first class citizen and everyone's answer is just an ugly hack. – Victorio Berra May 12 '23 at 16:39