asp.net conditionally disable a tag helper (textar

2019-01-11 10:58发布

问题:

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?

回答1:

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>



回答2:

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; }
}


回答3:

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



回答4:

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"