Tengo una ASP.Net MVC 3 aplicación web y voy a añadir una casilla de verificación para una página de vista el uso de la HtmlHelper clase, como este…

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

Lo que quiero hacer es condicionalmente agregar el atributo disabled basan en una visión del estado de la propiedad. Básicamente, el siguiente sería lo ideal…

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

Por desgracia, debido a la naturaleza del atributo disabled, esto no va a funcionar porque cualquier valor asignado al atributo disabled (incluso «false») se traduce como verdadero.

Ya he pensado en un par de soluciones para dar la vuelta a este problema, así que la pregunta no es ¿cómo puedo hacer esto. Pero más bien, hay una manera simple como el método deseado de arriba? o tengo que recurrir a uno de los siguientes?..

Lo sé que yo podría hacer…

  1. Crear un if/else y escribir en diferentes Html.CheckBox líneas (no grandes para facilitar la lectura – y posible con lanzar una marca de advertencia – no estoy seguro)

  2. Saltar HtmlHelper de la clase y de la mano de escritura de la etiqueta, permitiendo una mejor condicionalmente atributos (mantiene el código más corto, pero añade incoherencia)

  3. Crear un helper personalizado que toma un «discapacitado» parámetro (la solución más limpia, pero requiere no deseados que métodos adicionales: probablemente la mejor opción hasta el momento, aunque)

InformationsquelleAutor musefan | 2011-11-02

6 Comentarios

  1. 49

    Definir esta en algún lugar de la vista/ayudantes

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

    A continuación, utilice :

    @Html.TextBox("name", "value", @getHtmlAttributes(Model.ReadOnly, "test"))
    • Buena respuesta. Tuve que terminó haciendo la misma lógica, excepto con una sola línea (ternario, creo) condición como parte del Html.Casilla de verificación llamada. Su solución es mucho más agradable, gracias 😉
    • Gracias, por la información, tengo la sospecha de que la mejor manera es definir un EditorTemplate para el modelo, la definición de la función internamente y proporcionando también una especie de lado del cliente con jQuery magia para hacer todo. Por ejemplo, en el evento Load de un DIV contenedor.
    • mmm.. el ejemplo de arriba no funciona cuando lo uso con .TextBoxFor() (en Lugar de .TextBox() ) – tipo Anónimo proyección de inicializador debe ser simple nombre o el acceso de los miembros de expresión…
    • Cómo hacer los mismo para agregar disable opcionalmente ?
    • Sólo añadir un bool parámetro a la función y establecer el valor de @readonly en consecuencia. He perdido el contacto con .NET MVC así que realmente no sé si esta respuesta todavía se aplica con la última versión (espero que hayas añadido algunos mejor manera de hacer esto).
  2. 31

    Aquí está mi respuesta de esta pregunta similar: https://stackoverflow.com/a/13922813/495000


    He creado el siguiente Ayudante – toma un valor booleano y un objeto anónimo. Si está deshabilitado, es cierto, se añade el atributo disabled para el objeto anónimo (que en realidad es un Diccionario) con el valor de «discapacidad», de lo contrario no se le añade la propiedad en todo.

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

    Un ejemplo de ello en acción:

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

    Una gran ventaja de este enfoque para mí era que funciona con prácticamente todos los de la MVC HtmlHelpers ya que todos ellos tienen Sobrecargas que aceptar una RouteValueDictionary en lugar de un objeto anónimo.

    Advertencias:

    HtmlHelper.AnonymousObjectToHtmlAttributes() utiliza algunas de fantasía en el código ninja de trabajo para hacer las cosas. No estoy del todo seguro de cómo performante es… pero ha sido suficiente para lo que lo uso para. Su kilometraje puede variar.

    No me gusta especialmente el nombre de ella -, pero yo no podía llegar con algo mejor. El cambio de nombre es fácil.

    Tampoco me encanta el uso de la sintaxis, pero de nuevo no pude llegar a algo mejor. No debería ser difícil de cambiar. Un método de extensión en el objeto es una idea… terminarías con new { @class = "someClass" }.ConditionalDisable(true) pero, entonces, si sólo desea desactivar el atributo y no tiene nada adicional para agregar terminas con algo bruto como new {}.ConditionalDisable(true); y también terminará con un método de extensión que se muestra para todos los object… que probablemente no es deseable.

    • inteligente. elegante.
    • (bienvenido a 300)
    • Una solución más elegante. Este es el mejor que he encontrado. He considerado un método de extensión antes, pero eso sería demasiado general.
    • Esta es una gran solución, pero me parece que no puede llegar a trabajar con Html.ActionLink
  3. 10

    Si quieres más concisa de la sintaxis, sin necesidad de una función auxiliar, se puede utilizar un ternario declaración de la hora de definir el diccionario usado para los atributos html de la @HTML.Casilla de verificación ayudante…

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

    En este caso es el Modelo.ReadOnly es false, null pasa como el diccionario de atributos de html.

    • Esto podría llegar a ser muy detallado si la configuración de otros atributos.
    • no podría usted entonces sólo la instalación de una propiedad en su punto de vista[modelo] que hace todo el pesado cálculos por usted? A continuación, en la cshtml, es tan simple como el ejemplo de arriba.
    • Esto no funciona si se desea ajustar la @de la propiedad de clase en la falsa condición.
  4. 1

    Se realiza la adición del atributo disabled lado del cliente que funciona para mí. Nota usted debe comprobar que los campos pueden modificarse lado del servidor, pero eso es cierto para cuando el atributo disabled es declarado decorativamente también.

    En este ejemplo he desactivado todos los childeren de un formulario con jQuery.

        if (Model.CanEdit)
        {
            <script type="text/javascript">
    
                $(document).ready(function() {
    
                    $('#editForm *').attr('disabled', true);
                });
    
            </script>
        }
  5. 1
    @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;
    }
    }
  6. 1

    ¿Qué piensa usted acerca de mi simple solución? Funciona fácilmente con los posibles HtmlAttributes tipos:

    • Dictionary<string, object>
    • Anonymous Object:

    Primera agregar el siguiente sencillo extension class a su proyecto:

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

    Ahora a la Vista:

    Ejemplo1 (HtmlAttributes tipo como Anonymous Object)

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

    Ejemplo 2 (HtmlAttributes tipo como Dictionary<string, object>)

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

    Ahora acaba de cambiar la hasDisabled valor a true o false!


    Ejemplo3 (Varios condicional propiedades)

    @{
    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))
    .
    • Esto es genial, gracias! Uno de los comentarios, a pesar de que: recomiendo el uso de HtmlHelper.AnonymousObjectToHtmlAttributes en lugar de UnderlineToDashInDictionaryKeys porque ya está incorporado. 😉

Dejar respuesta

Please enter your comment!
Please enter your name here