Comment ajouter une deuxième classe CSS avec une valeur conditionnelle dans Razor MVC 4

149

Bien que Microsoft ait créé un rendu automatique des attributs html dans razor MVC4, il m'a fallu un certain temps pour découvrir comment rendre une deuxième classe css sur un élément, basée sur une expression de rasoir conditionnelle. J'aimerais le partager avec toi.

Basé sur une propriété de modèle @ Model.Details, je souhaite afficher ou masquer un élément de liste. S'il y a des détails, un div doit être affiché, sinon, il doit être masqué. En utilisant jQuery, tout ce que j'ai à faire est d'ajouter une classe show ou hide, respectivement. Pour d'autres raisons, je souhaite également ajouter une autre classe, "détails". Donc, ma majoration devrait être:

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

Ci-dessous, je montre quelques tentatives infructueuses (le balisage résultant en supposant qu'il n'y a pas de détails).

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

rendra ceci: <div class="details" hide="">.

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

rendra ceci: <div class=""details" hide&quot;="">.

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

rendra ceci: <div class="'details" hide&#39;="">.

Aucun de ces éléments n'est une majoration correcte.

R. Schreurs
la source
Toutes vos premières solutions auraient fonctionné si vous les avez enveloppées dans une nouvelle instance de MvcHtmlString ou utilisé Html.Raw
Kyle

Réponses:

301

Je crois qu'il peut encore y avoir une logique valable sur les vues. Mais pour ce genre de choses je suis d'accord avec @BigMike, il est mieux placé sur le modèle. Cela dit, le problème peut être résolu de trois manières:

Votre réponse (en supposant que cela fonctionne, je n'ai pas essayé ceci):

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

Deuxième option:

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

Troisième option:

<div class="@("details " + (Model.Details.Count>0 ? "show" : "hide"))">
von c.
la source
2
J'ai accepté cela comme réponse, car il offre plus d'options que les miennes.
R. Schreurs
18
La 2ème option provoque l'erreurThe "div" element was not closed
intrépidis
6
Bien sûr, ce sera le cas car ce qui est écrit ici n'est pas le code complet mais plutôt la partie du code qui est en question. Qui sait combien d'autres éléments sont dans la div;)
von v.16
Cela n'a pas fonctionné pour moi. J'ai eu cette erreur'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
Comment votre problème est-il lié à la question posée?
von v.11
69

Ce:

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

rendra ceci:

    <div class="details hide">

et c'est la majoration que je veux.

R. Schreurs
la source
1
Je n'aime pas avoir de logique dans les vues, même si c'est une logique triviale, je préfère utiliser un objet ModelView avec une méthode getDetailClass ().
BigMike
29
Personnellement, je préfère la logique triviale, avoir une méthode getDetailCssClass signifie que votre modèle est conscient de votre vue, décomposant cette abstraction. J'ajouterais une méthode HasDetails au modèle pour réduire la logique requise dans la vue, puis je laisserais la logique de classe css à la vue, ce qui signifie que vous n'avez pas à joncher la vue @Model.Details.Count > 0. par exemple<div class="details @(@Model.HasDetails ? "show" : "hide")">
Chris Diver
26

Vous pouvez ajouter une propriété à votre modèle comme suit:

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

et alors votre vue sera plus simple et ne contiendra aucune logique:

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

Cela fonctionnera même avec de nombreuses classes et ne rendra pas la classe si elle est nulle:

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

avec 2 propriétés non nulles rendra:

    <div class="class1 class2"/>

si class1 est nul

    <div class=" class2"/>
synchronisé
la source
11
Je pense qu'il vaut mieux laisser la vue définir des choses telles que les classes css. Rappelez-vous que la vue devrait pouvoir être profondément modifiée (ou même remplacée) sans que cela n'affecte le modèle de vue
tobiak777
1
Bien que je sois d'accord avec Reddy en général, il peut y avoir des cas dans lesquels il peut être justifié de le faire comme le dit syned. Je l'ai fait exactement comme ça. Dans mon cas, je me fie à un objet ViewModel plein d'informations pour rendre la vue, ce n'est pas seulement un objet de données.
Gonzalo Méndez
1
Je l'utiliserais comme ça s'il y avait plus de 2 résultats. Par exemple pour 5 classes possibles. Que ce serait compliqué de le garder en vue.
Mateusz Migała
1
La vue est au bon endroit. Formatez-le bien en affectations de variables dans un bloc de code et ce ne sera pas compliqué.
Tom Blodget
3

Vous pouvez utiliser la fonction String.Format pour ajouter une deuxième classe en fonction de la condition:

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