ASP.NET如何有条件地禁用标签助手(textarea)?

48

我想根据模型的条件来启用或禁用文本区域,并且我正在使用文本区域标签助手。 换句话说,就像这样:

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

但是我遇到了以下设计时错误:标签助手“textarea”的元素属性声明区域不得有C#。

然后我尝试了:

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

虽然没有显示任何设计时错误,但呈现效果如下: Model.MustDisable==true 会呈现为 disabled='disabled',而Model.MustDisable==false则不含有disabled属性。 因此,文本区域将始终被禁用。

接着我试了一下(去掉了's):

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

这段代码在设计时没有显示任何错误,但呈现的结果与之前的相同。

我该如何正确实现它?


1
为什么不也将禁用属性有条件地呈现? - Travis J
4个回答

56

其实很简单,disable属性已经按照你的要求起作用了 - 你可以传入一个布尔值:

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

如果为假,则不会呈现disabled属性:

<textarea></textarea>

如果为真,则将disabled属性设置为"disabled":

<textarea disabled="disabled"></textarea>

4
@RyanO'Neill 这就是它的工作原理!试一试,你就会明白 :-)。如果你发送了 false,TagHelper 就不会打印出该属性。我也更新了我的答案以进行澄清。 - Daniel Stackenland
1
@Jess - 这是一个内置的标签助手(我不知道是否应该称其为魔法)。https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers - Daniel Stackenland
2
哇,太神奇了。在Core 3.1中确认 - 这应该是被接受的答案。 - Brian MacKay
1
@vmh 请接受这个答案。它按预期工作,当传递值 false 时,不会呈现 disabled 属性。 - RoLYroLLs
1
@Abol_Fa 我没有尝试过,但我认为你可以添加一个括号 <textarea asp-for="Doc" disabled="@(!Model.MustDisable)"></textarea>。否则,在您的模型中添加一个额外的方法并使用!运算符很容易。 - Daniel Stackenland
显示剩余4条评论

48

我在使用


5
我认为这个在所有浏览器上都不会起作用。'disabled=""' 会导致输入框变成禁用状态。 - user942620
@user942620,你是正确的,但在使用双引号代替null时要小心。 - Mohamed Badr
非常感谢!我仍然想知道为什么微软不允许使用普通的@(condition ? "disabled" : ""),但是我本来打算扩展TagHelper(对于这样一个小事情来说太麻烦了!)而这个解决方案救了我的一天!;) - Fábio Duque Silva
2
@user942620 我知道这已经很老了,但是你的评论需要进行更正。所有浏览器都应该将 disabled="false" 渲染为禁用状态,但我们实际上并不是在编写 HTML。标签助手正在编写 HTML。如果标签助手看到 disabled="false",它就不会呈现 disabled 属性。 - Auspex

19

textarea标签助手无法直接支持有条件地呈现禁用的文本区域。但是您可以始终扩展TextAreaTagHelper并添加此功能。

因此,创建一个从TextAreaTagHelper类继承的新类。

[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);
    }
}
在您的_ViewImports.cshtml文件中,使用@addTagHelper指令指定包含上述类定义的程序集,以便我们的新标签助手可用于其他razor视图。
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*,YourAssemblyNameHere"

现在在你的视图中,你可以像这样使用它

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

其中SomeViewModel有一个DocMustDisable属性。

public class YourSomeViewModel
{
  public string Doc { set;get; }
  public bool MustDisable  { set;get; }
}

1
这比最受欢迎的答案效果更好,而且使用三元表达式添加禁用属性也更美观。谢谢! - nbokmans

3

因为我声望不够高,不能在Shyju的答案下添加评论,所以我会单独发帖。

如果你继承了默认标记帮助程序之一,并且在_ViewImports.cshtml中同时注册了默认标记帮助程序和自定义标记帮助程序,那么这两个标记帮助程序都将针对指定的标记执行。

例如以下情况:

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

使用以下_ViewImports.cshtml文件:

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

每个textarea标签都将执行MyCustomTextAreaTextAreaTagHelper

我没有注意到textarea生成的输出有任何问题,但我遇到了从其他默认标签助手继承的问题。解决方案是在_ViewImports.cshtml中删除默认标签助手。

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

@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.InputTagHelper,Microsoft.AspNetCore.Mvc.TagHelpers - Andriy Zymenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接