asp.net conditionally disable a tag helper (textarea)
Asked Answered
G

4

49

I want to enable or disable a textarea depending on a condition that evalueates from the model, and I am using the textarea tag helper. In other words, something like this:

<textarea asp-for="Doc" @(Model.MustDisable ? "disabled" : "")></textarea>

But I got the following design-time error: The tag helper 'textarea' must not have C# in element's attribute declaration area.

Then I tried:

<textarea asp-for="Doc" disabled='@(Model.MustDisable ? "disabled" : "")'></textarea>

which did not show any design time error but it renders like this: Model.MustDisable==true renders disabled='disabled' AND Model.MustDisable==false renders disabled. So the text area will always be disabled.

Then I tried (removing the 's):

textarea asp-for="Doc" disabled=@(Model.MustDisable ? "disabled" : "")></textarea>

which did not show any design time error but it renders the same as the previous one.

How can I implement this the right way?

Garrett answered 19/1, 2016 at 0:27 Comment(1)
Why not just also render the disabled attribute conditionally as well?Wheelhorse
Z
58

It is actually very simple, the disable attribute is already working as you want - you can pass in a boolean value:

<textarea asp-for="Doc" disabled="@Model.MustDisable"></textarea>

if false the disabled attribute is not rendered:

<textarea></textarea>

if true the disabled attribute is set to "disabled":

<textarea disabled="disabled"></textarea>
Zahara answered 21/6, 2018 at 9:22 Comment(9)
Although this might work, it could break on different browsers or later versions of those browsers as it is not standard and depends how the browser vendor interprets the disabled attribute. In brief, if disabled is output at all then that field will be disabled. The value true/false should not matter, just the attribute on it's own should be output. For an enabled field, omit the attribute completely. Hence why this is not the chosen answer.Pawn
@RyanO'Neill That's how it works! Try it out and you'll see :-). If you send in false the TagHelper will not print out the attribute at all.I update my answer to clarify also.Zahara
@Jess - it's a built-in Tag Helper (I don't know if I'd call it magic) learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpersZahara
Confirmed. This does indeed work - Razor or MVC is doing some magic to make this happen. (using .NET Core 2.2.)Peonage
Wow, magic. Confirmed in Core 3.1 - this should be the accepted answer.Maibach
if you use a variable, you need to place it between braces: disabled="@(inputDisabled)"Stan
@vmh Please accept this as the answer. it works as expected, without rendering the disabled attribute when the value false is passed.Kimball
@DanielStackenland How can I use the ! operator? writing <textarea asp-for="Doc" disabled="@!Model.MustDisable"></textarea>will cause an error.Overword
@Overword I haven't tried, but I think you can add a paranteces <textarea asp-for="Doc" disabled="@(!Model.MustDisable)"></textarea> . Otherwise, it's easy to add an extra method in your Model with the !-operator.Zahara
I
48

I was facing the same issue with select tag helper, i tried few things and it worked. Try this-

<textarea asp-for="Doc" disabled="@(Model.MustDisable ? "disabled" : null)"></textarea>
Intercalate answered 14/7, 2016 at 6:29 Comment(4)
I don't think this will work on all browsers. ' disabled="" ' will cause an input to be disabled.Desecrate
@Desecrate you are right but just in case of using "" instead of nullZacharie
This!!! Thanks a lot! I still wonder why MS doesn't allow a regular @(condition ? "disabled" : ""), but I was going to extend the TagHelper (too much work for such a small thing!) and this solution saved my day! ;)Ligurian
@Desecrate I know this is very old, but your comment needs to be corrected. It's true that ALL browsers should render disabled="false" as disabled, but we're not actually writing HTML here. The tag helper is writing HTML. And if the tag helper sees disabled="false", it doesn't render a disabled attribute.Wooten
P
19

The textarea tag helper does not have direct support to conditionally render a disabled text area. But you can always extend the TextAreaTagHelper and add this feature.

So create a new class which inherits from the TextAreaTagHelper class.

[HtmlTargetElement("textarea", Attributes = ForAttributeName)]
public class MyCustomTextArea : TextAreaTagHelper
{
    private const string ForAttributeName = "asp-for";

    [HtmlAttributeName("asp-is-disabled")]
    public bool IsDisabled { set; get; }

    public MyCustomTextArea(IHtmlGenerator generator) : base(generator)
    {
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (IsDisabled)
        {
            output.Attributes["disabled"] = "disabled";
        }           
        base.Process(context, output);
    }
}

In your _ViewImports.cshtml file, using the @addTagHelper directive, specify the assembly where the above class is defined so that our new tag helper is available in other razor views.

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*,YourAssemblyNameHere"

Now in your views, you can use it like

@model YourSomeViewModel
<textarea asp-for="Doc" asp-is-disabled="Model.MustDisable"></textarea>

where SomeViewModel has a Doc and MustDisable property.

public class YourSomeViewModel
{
  public string Doc { set;get; }
  public bool MustDisable  { set;get; }
}
Purveyor answered 19/1, 2016 at 4:10 Comment(1)
Works better than the top upvoted answer and is also a bit nicer than using a ternary expression to add the disabled attribute. Thanks!Metzgar
C
3

I am posting this separately since I don't have enough reputation to add a comment to Shyju's answer.

If you inherit from one of the default tag helpers and then register both the default tag helpers and your custom tag helper in _ViewImports.cshtml, then both tag helpers will be executed for the specified tags.

For the following:

[HtmlTargetElement("textarea", Attributes = ForAttributeName)]
public class MyCustomTextArea : TextAreaTagHelper
{
    private const string ForAttributeName = "asp-for";
...

With the following _ViewImports.cshtml:

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*,YourAssemblyNameHere"

Both MyCustomTextArea and TextAreaTagHelper will be executed for each textarea tag.

I did not notice any problems with the output generated for textareas, but I have run into problems inheriting from other default tag helpers. The solution is to remove the default tag helper in _ViewImports.cshtml.

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*,YourAssemblyNameHere"
@removeTagHelper "Microsoft.AspNet.Mvc.TagHelpers.TextAreaTagHelper, Microsoft.AspNet.Mvc.TagHelpers"
Companionable answered 11/4, 2016 at 16:11 Comment(1)
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.InputTagHelper, Microsoft.AspNetCore.Mvc.TagHelpersAceto

© 2022 - 2024 — McMap. All rights reserved.