asp.net-mvc MVC 3:使用 HtmlHelpers 有条件地添加禁用属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7978137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:33:40  来源:igfitidea点击:

MVC 3: Conditionally Adding the Disabled Attribute with the HtmlHelpers

asp.net-mvcasp.net-mvc-3html-helper

提问by musefan

I have an ASP.Net MVC 3 web application and I am adding a check box to a view page using the HtmlHelper class, like this...

我有一个 ASP.Net MVC 3 web 应用程序,我正在使用 HtmlHelper 类向视图页面添加一个复选框,就像这样......

@Html.CheckBox("CheckBox1", true, new { @class = "Class1" })

What I want to do is conditionally add the disabled attribute based on a view state property. Basically the following would be ideal...

我想要做的是根据视图状态属性有条件地添加禁用属性。基本上以下将是理想的......

@Html.CheckBox("CheckBox1", true, new { @class = "Class1", @disabled = Model.ReadOnly })

Unfortunately, due to the nature of the disabled attribute, this will not work because anyvalue assigned to the disabled attribute (even "false") will be translated as true.

不幸的是,由于 disabled 属性的性质,这将不起作用,因为分配给 disabled 属性的任何值(甚至“false”)都将被转换为 true。

I have already thought of a few solutions to get round this problem, so the question is not how can I do this. But rather, is there a simple way like the desired method above? or do I have to resort to one of the following?..

我已经想到了一些解决方案来解决这个问题,所以问题不是我该怎么做。而是有没有像上面所期望的方法简单的方法?还是我不得不求助于下列情况之一?..

What I know I could do...

我知道我能做什么...

  1. Create an if/else statement and write to different Html.CheckBoxlines (not great for readability - and possible with throw a mark-up warning - not sure)

  2. Skip the HtmlHelper class and hand write the tag allowing for better conditionally attributes (keeps the code shorter, but adds inconsistency)

  3. Create a custom helper that takes a "disabled" parameter (the cleanest solution, but requires undesired extra methods - probably the best option so far though)

  1. 创建一个 if/else 语句并写入不同的Html.CheckBox行(不利于可读性 - 并且可能抛出标记警告 - 不确定)

  2. 跳过 HtmlHelper 类并手写标记以提供更好的条件属性(使代码更短,但增加了不一致)

  3. 创建一个带有“禁用”参数的自定义帮助程序(最干净的解决方案,但需要不需要的额外方法 - 不过可能是迄今为止最好的选择)

采纳答案by BigMike

Define this somewhere in your view/helpers

在您的视图/助手中的某处定义它

@functions {
 object getHtmlAttributes (bool ReadOnly, string CssClass) 
 {
     if (ReadOnly) {
         return new { @class = CssClass, @readonly = "readonly" };
     }
     return new { @class = CssClass };
 }
}

Then use :

然后使用:

@Html.TextBox("name", "value", @getHtmlAttributes(Model.ReadOnly, "test"))

回答by Mir

Here's my answer from this similar question: https://stackoverflow.com/a/13922813/495000

这是我对这个类似问题的回答:https: //stackoverflow.com/a/13922813/495000



I created the following Helper - it takes a boolean and an anonymous object. If disabled is true, it adds the disabled attribute to the anonymous object (which is actually a Dictionary) with the value "disabled", otherwise it doesn't add the property at all.

我创建了以下 Helper - 它需要一个布尔值和一个匿名对象。如果 disabled 为 true,则将 disabled 属性添加到值为“disabled”的匿名对象(实际上是一个 Dictionary),否则它根本不添加该属性。

public static RouteValueDictionary ConditionalDisable(
   bool disabled, 
   object htmlAttributes = null)
{
   var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

   if (disabled)
      dictionary.Add("disabled", "disabled");

   return dictionary;
}

An example of it in action:

它的一个例子:

@Html.TextBoxFor(m => m.SomeProperty,    
   HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))

One huge advantage to this approach for me was that it works with virtually all of the MVC HtmlHelpers since they all have Overloads that accept a RouteValueDictionary instead of an anonymous object.

对我来说,这种方法的一个巨大优势是它几乎适用于所有 MVC HtmlHelper,因为它们都具有接受 RouteValueDictionary 而不是匿名对象的重载。

Caveats:
HtmlHelper.AnonymousObjectToHtmlAttributes()uses some fancy code ninja work to get things done. I'm not entirely sure how performant it is... but it's been sufficient for what I use it for. Your mileage may vary.

警告
HtmlHelper.AnonymousObjectToHtmlAttributes()使用一些花哨的代码忍者工作来完成工作。我不完全确定它的性能如何......但是对于我使用它的目的来说已经足够了。你的旅费可能会改变。

I don't especially like the name of it - but I couldn't come up with anything better. Renaming is easy.

我不是特别喜欢它的名字——但我想不出更好的了。重命名很容易。

I also don't love the usage syntax - but again I couldn't come up with anything better. It shouldn't be difficult to change. An extension method on object is one idea... you'd end up with new { @class = "someClass" }.ConditionalDisable(true)but then if you only want the disable attribute and don't have anything additional to add you end up with something gross like new {}.ConditionalDisable(true);and you also end up with an extension method that shows up for all object... which is probably not desirable.

我也不喜欢使用语法 - 但我又想不出更好的办法。改变应该不难。对象上的扩展方法是一个想法......你最终会得到new { @class = "someClass" }.ConditionalDisable(true)但是如果你只想要禁用属性并且没有任何额外的东西来添加你最终会得到一些类似的东西new {}.ConditionalDisable(true);并且你最终也会得到一个扩展显示给所有人的方法object......这可能是不可取的。

回答by Andy Brudtkuhl

If you want more terse syntax without requiring a helper function, you could use a ternary statement when defining the dictionary used for the html attributes of the @HTML.Checkbox helper...

如果您想要更简洁的语法而不需要辅助函数,则可以在定义用于 @HTML.Checkbox 辅助函数的 html 属性的字典时使用三元语句...

@Html.CheckBox("CheckBox1", true, Model.ReadOnly 
       ? new { @class = "Class1", @disabled = Model.ReadOnly } 
       : null)

In this case is Model.ReadOnly is false, null gets passed as the dictionary of html attributes.

在这种情况下,Model.ReadOnly 为 false,null 作为 html 属性字典传递。

回答by gb2d

Performing the addition of the disabled attribute client side works for me. Note you should check which fields are allowed to be edited server side, but that is true for where the disabled attribute is declared decoratively also.

执行添加禁用属性客户端对我有用。请注意,您应该检查允许在服务器端编辑哪些字段,但对于装饰性声明 disabled 属性的情况也是如此。

In this example I have disabled all childeren of a form using jQuery.

在这个例子中,我使用 jQuery 禁用了表单的所有 childeren。

    if (Model.CanEdit)
    {
        <script type="text/javascript">

            $(document).ready(function() {

                $('#editForm *').attr('disabled', true);
            });

        </script>
    }

回答by Alan Singfield

@Html.TextBoxFor(m => m.FieldName, Html.FixBoolAttributes(new {
    @class = "myClass",
    @readonly = myFlag  
}))


public static class BooleanAttributeFix
{
    /// <summary>
    /// Normalises HTML boolean attributes so that readonly=true becomes readonly="readonly" and
    /// readonly=false removes the attribute completely.
    /// </summary>
    /// <param name="htmlHelper"></param>
    /// <param name="htmlAttributes"></param>
    /// <returns></returns>
    public static RouteValueDictionary FixBoolAttributes(this HtmlHelper htmlHelper, object htmlAttributes)
    {
        var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

        foreach(var attrName in new[] { "disabled", "readonly" })
        {
            object value;
            if(attrs.TryGetValue(attrName, out value))
            {
                if(isTruthy(value))
                {
                    // Change from readonly="true" to readonly="readonly"
                    attrs[attrName] = attrName; 
                }
                else
                {
                    // Remove attribute entirely
                    attrs.Remove(attrName); 
                }
            }
        }
        return attrs;
    }

    /// <summary>
    /// Apply similar loose rules like javascript does for whether a value is true or not.
    /// e.g. 1 = true, non-empty string = true and so on.
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    private static bool isTruthy(object val)
    {   
        if(val == null)
            return false;

        if(val is string)
        {
            return !String.IsNullOrEmpty((string)val);
        }

        Type t = val.GetType();

        if(t.IsValueType && Nullable.GetUnderlyingType(t) == null)
        {
            // If a non-nullable value type such as int we want to check for the
            // default value e.g. 0.
            object defaultValue = Activator.CreateInstance(t);

            // Use .Equals to compare the values rather than == as we want to compare
            // the values rather than the boxing objects.
            // See http://stackoverflow.com/questions/6205029/comparing-boxed-value-types
            return !val.Equals(defaultValue);
        }

        return true;
    }
}

回答by RAM

What do you think about my simplesolution? It works easily with both possible HtmlAttributestypes:

您如何看待我的简单解决方案?它适用于两种可能的HtmlAttributes类型:

  • Dictionary<string, object>
  • Anonymous Object:
  • Dictionary<string, object>
  • Anonymous Object

Firstadd the following simple extension classto your project:

首先将以下简单添加extension class到您的项目中:

public static class HtmlAttributesExtensions
{
    public static IDictionary<string, object> AddHtmlAttrItem(this object obj, string name, object value, bool condition)
    {
        var items= !condition ? new RouteValueDictionary(obj) : new RouteValueDictionary(obj) {{name, value}};
        return UnderlineToDashInDictionaryKeys(items);
    }
    public static IDictionary<string, object> AddHtmlAttrItem(this IDictionary<string, object> dictSource, string name, object value, bool condition)
    {
        if (!condition)
            return dictSource;

        dictSource.Add(name, value);
        return UnderlineToDashInDictionaryKeys(dictSource);
    }
    private static IDictionary<string, object> UnderlineToDashInDictionaryKeys(IDictionary<string,object> items)
    {
        var newItems = new RouteValueDictionary();
        foreach (var item in items)
        {
            newItems.Add(item.Key.Replace("_", "-"), item.Value);
        }
        return newItems;
    }
}


Now in View:

现在在视图中:

Example1(HtmlAttributestype as Anonymous Object)

示例 1 HtmlAttributes类型为Anonymous Object

@{
  var hasDisabled=true; 
}

@Html.CheckBox("CheckBox1"
              , true
              , new { @class = "Class1"}
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

Example 2(HtmlAttributestype as Dictionary<string, object>)

示例 2 HtmlAttributes键入 as Dictionary<string, object>

@Html.CheckBox("CheckBox1"
              , true
              , new Dictionary<string, object> { { "class", "Class1" }
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

Now just change the hasDisabledvalue to trueor false!

现在只需将hasDisabled值更改为trueor false



Example3(Multiple conditional properties)

示例 3 (多个条件属性)

@{
  var hasDisabled=true;
  var hasMax=false ;
  var hasMin=true ;
}

@Html.CheckBox("CheckBox1"
              , true
              , new { @class = "Class1"}
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled)
               .AddHtmlAttrItem("data-max", "100", hasMax)
               .AddHtmlAttrItem("data-min", "50", hasMin))
.

回答by sam80e

I liked @gb2d answer, here it is in JS using getElementsByClassName taken from here getElementByClass().setAttribute doesn't work

我喜欢@gb2d 的答案,这里是在 JS 中使用 getElementsByClassName 从这里获取的 getElementByClass().setAttribute 不起作用

<script type="text/javascript">
    var list, index;
    list = document.getElementsByClassName("form-control");
    for (index = 0; index < list.length; ++index) {
        list[index].setAttribute('disabled', true);
    }
</script>