Cómo agregar una segunda clase css con un valor condicional en razor MVC 4

149

Si bien Microsoft ha creado una representación automática de los atributos html en la maquinilla de afeitar MVC4, me llevó bastante tiempo descubrir cómo representar una segunda clase css en un elemento, basada en una expresión de maquinilla condicional. Me gustaría compartirlo contigo.

Basado en una propiedad de modelo @ Model.Details, quiero mostrar u ocultar un elemento de la lista. Si hay detalles, se debe mostrar un div; de lo contrario, se debe ocultar. Usando jQuery, todo lo que necesito hacer es agregar un show u ocultar clase, respectivamente. Para otros fines, también quiero agregar otra clase, "detalles". Entonces, mi margen de beneficio debería ser:

<div class="details show">[Details]</div> o <div class="details hide">[Details]</div>

A continuación, muestro algunos intentos fallidos (marcado resultante suponiendo que no hay detalles).

Este: <div @(@Model.Details.Count > 0 ? "class=details show" : "class=details hide")>,

esto hará que: <div class="details" hide="">.

Esta: <div @(@Model.Details.Count > 0 ? "class=\"details show\"" : "class=\"details hide\"")> .

esto hará que: <div class=""details" hide&quot;="">.

Esta: <div @(@Model.Details.Count > 0 ? "class='details show'" : "class='details hide'")>

esto hará que: <div class="'details" hide&#39;="">.

Ninguno de estos son marcas correctas.

R. Schreurs
fuente
Todas tus primeras soluciones habrían funcionado si las hubieras incluido en una nueva instancia de MvcHtmlString o hubieras usado Html.Raw
Kyle el

Respuestas:

301

Creo que todavía puede haber una lógica válida en las vistas. Pero para este tipo de cosas estoy de acuerdo con @BigMike, es mejor colocarlo en el modelo. Dicho esto, el problema se puede resolver de tres maneras:

Su respuesta (suponiendo que esto funcione, no lo he intentado):

<div class="details @(@Model.Details.Count > 0 ? "show" : "hide")">

Segunda opción:

@if (Model.Details.Count > 0) {
    <div class="details show">
}
else {
    <div class="details hide">
}

Tercera opción:

<div class="@("details " + (Model.Details.Count>0 ? "show" : "hide"))">
von v.
fuente
2
He aceptado esto como la respuesta, ya que ofrece más opciones que las mías.
R. Schreurs
18
La segunda opción causa el errorThe "div" element was not closed
intrepidis
66
Por supuesto, lo que está escrito aquí no es el código completo, sino la parte del código en cuestión. Quién sabe cuántos otros elementos hay en el div;)
von v.
No funciono para mi. Recibí este error'ClubsModel' does not contain a definition for 'ClubsFilter' and no extension method 'ClubsFilter' accepting a first argument of type 'ClubsModel' could be found (are you missing a using directive or an assembly reference?)
Martin Erlic,
¿Cómo se relaciona su problema con la pregunta publicada?
von v.
69

Esta:

    <div class="details @(Model.Details.Count > 0 ? "show" : "hide")">

renderizará esto:

    <div class="details hide">

y es el marcado que quiero.

R. Schreurs
fuente
1
No me gusta tener lógica en las vistas, incluso si es lógica trivial, prefiero usar un objeto ModelView con un método getDetailClass ().
BigMike
29
Personalmente, prefiero la lógica trivial, tener un método getDetailCssClass significa que su Modelo conoce su Vista, desglosando esa abstracción. Agregaría un método HasDetails al Modelo para reducir la lógica requerida en la vista, luego dejaría la lógica de la clase css en la vista, eso significa que no tiene que ensuciar la vista @Model.Details.Count > 0. por ejemplo<div class="details @(@Model.HasDetails ? "show" : "hide")">
Chris Diver el
26

Puede agregar propiedades a su modelo de la siguiente manera:

    public string DetailsClass { get { return Details.Count > 0 ? "show" : "hide" } }

y luego su vista será más simple y no contendrá ninguna lógica:

    <div class="details @Model.DetailsClass"/>

Esto funcionará incluso con muchas clases y no representará la clase si es nula:

    <div class="@Model.Class1 @Model.Class2"/>

con 2 propiedades no nulas representará:

    <div class="class1 class2"/>

si class1 es nulo

    <div class=" class2"/>
Syned
fuente
11
Creo que es mejor dejar que la vista defina cosas como las clases css. Recuerde que la vista debería poder modificarse (o incluso reemplazarse) sin que afecte al Modelo de vista
tobiak777
1
Aunque estoy de acuerdo con reddy en general, puede haber casos en los que pueda justificarse hacerlo de la manera en que Syned lo dice. Lo hice exactamente así. En mi caso, confío en un objeto ViewModel lleno de información para representar la vista, no es solo un objeto de datos.
Gonzalo Méndez
1
Lo usaría así si hubiera más de 2 resultados. Por ejemplo para 5 clases posibles. De lo que sería complicado tenerlo a la vista.
Mateusz Migała
1
La vista es el lugar correcto. Formatee bien como asignaciones variables en un bloque de código y no será complicado.
Tom Blodget
3

Puede usar la función String.Format para agregar una segunda clase según la condición:

<div class="@String.Format("details {0}", Details.Count > 0 ? "show" : "hide")">
Chetan Gaonkar
fuente