В MVC 3: условно добавив атрибут disabled вспомогательные методы HTML приложения


у меня есть ASP.Net веб-приложение MVC 3, и я добавляю флажок на страницу просмотра с помощью класса HtmlHelper, например...

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

то, что я хочу сделать, это условно добавить атрибут disabled, основанный на представлении государственным имуществом. В принципе, следующее Было бы идеально...

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

к сожалению, в силу природы атрибута disabled, это не будет работать, потому что любой присвоено значение атрибута disabled (даже "ложь") будет переведена как истина.

Я уже придумал несколько решений, чтобы обойти эту проблему, так что вопрос не в том как я могу это сделать. Но, скорее, есть ли простой способ, как желаемый метод выше? или мне придется прибегнуть к одному из следующих?..

то, что я знаю, я мог бы сделать...

  1. создайте оператор if / else и напишите в different Html.CheckBox линии (не отлично подходит для удобочитаемости - и возможно с предупреждением о надбавке - не уверен)

  2. пропустить класс HtmlHelper и вручную написать тег, позволяющий лучше условно атрибуты (сохраняет код короче, но добавляет несогласованность)

  3. создайте пользовательский помощник, который принимает параметр" disabled " (самое чистое решение, но требует нежелательных дополнительных методов - вероятно, лучший вариант до сих пор)

6 62

6 ответов:

определите это где-то в вашем представлении/помощники

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

затем использовать :

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

вот мой ответ на этот аналогичный вопрос:https://stackoverflow.com/a/13922813/495000


Я создал следующий помощник-он принимает логический и анонимный объект. Если disabled имеет значение true, он добавляет атрибут disabled к анонимному объекту (который на самом деле является словарем) со значением "disabled", в противном случае он вообще не добавляет свойство.

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

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

   return dictionary;
}

пример этого в действии:

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

один огромный преимущество этого подхода для меня заключалось в том, что он работает практически со всеми MVC HtmlHelpers, поскольку все они имеют перегрузки, которые принимают RouteValueDictionary вместо анонимного объекта.

предостережения:
HtmlHelper.AnonymousObjectToHtmlAttributes() использует некоторые фантазии код ниндзя работы, чтобы сделать вещи. Я не совсем уверен, насколько он эффективен... но этого было достаточно для того, для чего я его использую. Ваш пробег может отличаться.

мне не особенно нравится его название - но я не мог прийти что-нибудь получше. Переименование-это просто.

Я тоже не люблю синтаксис, но снова я не мог придумать ничего лучше. Это не должно быть трудно изменить. Метод расширения объекта-это одна идея... вы бы в конечном итоге с new { @class = "someClass" }.ConditionalDisable(true) но тогда, если вы хотите только отключить атрибут и нет ничего дополнительного, чтобы добавить вы в конечном итоге с чем-то грубым, как new {}.ConditionalDisable(true); и вы также получите метод расширения, который отображается для всех object... что, вероятно, не желательный.

Если вам нужен более краткий синтаксис, не требующий вспомогательной функции, вы можете использовать тернарный оператор при определении словаря, используемого для атрибутов html @HTML.Помощник флажок...

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

в данном случае модель.ReadOnly имеет значение false, null передается как словарь атрибутов html.

выполнение добавления отключенного атрибута на стороне клиента работает для меня. Примечание. Вы должны проверить, какие поля разрешено редактировать на стороне сервера, но это верно для того, где отключенный атрибут объявлен декоративно также.

в этом примере я отключил все childeren формы с помощью jQuery.

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

            $(document).ready(function() {

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

        </script>
    }
@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;
    }
}

что ты думаешь о моем простой решение? Он легко работает с обоими возможными HtmlAttributes типа:

  • Dictionary<string, object>
  • Anonymous Object:

первый добавить следующие простые 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;
    }
}

теперь в поле зрения:

Example1(HtmlAttributes тип as Anonymous Object)

@{
  var hasDisabled=true; 
}

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

Пример 2(HtmlAttributes тип Dictionary<string, object>)

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

теперь просто изменить hasDisabled значение true или false!


Example3(несколько условных свойства)

@{
  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))
.