Come aggiungere una seconda classe css con un valore condizionale in razor MVC 4


149

Mentre Microsoft ha creato un rendering automagico degli attributi HTML nel rasoio MVC4, mi ci è voluto un po 'di tempo per scoprire come eseguire il rendering di una seconda classe CSS su un elemento, basato su un'espressione condizionale del rasoio. Vorrei condividerlo con te.

Basato su una proprietà del modello @ Model.Details, voglio mostrare o nascondere un elemento dell'elenco. Se ci sono dettagli, dovrebbe essere mostrato un div, altrimenti dovrebbe essere nascosto. Usando jQuery, tutto ciò che devo fare è aggiungere uno spettacolo di classe o nascondere, rispettivamente. Per altri scopi, voglio anche aggiungere un'altra classe, "dettagli". Quindi, il mio mark-up dovrebbe essere:

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

Di seguito, mostro alcuni tentativi falliti (il markup risultante presuppone che non ci siano dettagli).

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

renderà questo: <div class="details" hide="">.

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

renderà questo: <div class=""details" hide&quot;="">.

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

renderà questo: <div class="'details" hide&#39;="">.

Nessuno di questi è markup corretto.


Tutte le tue prime soluzioni avrebbero funzionato se le avessi avvolte in una nuova istanza di MvcHtmlString o utilizzato Html.Raw
Kyle

Risposte:


301

Credo che ci possa essere ancora e una logica valida sulle viste. Ma per questo genere di cose sono d'accordo con @BigMike, è meglio collocato sul modello. Detto questo, il problema può essere risolto in tre modi:

La tua risposta (supponendo che funzioni, non ho provato questo):

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

Seconda opzione:

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

Terza opzione:

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

2
Ho accettato questa come risposta, poiché offre più opzioni delle mie.
R. Schreurs,

18
La seconda opzione provoca l'erroreThe "div" element was not closed
intrepidis,

6
Certo, come scritto qui non è il codice completo ma piuttosto la parte del codice in questione. Chissà quanti altri elementi ci sono nel div;)
von v.

Non ha funzionato per me. Ho avuto questo errore'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,

In che modo il tuo problema è correlato alla domanda pubblicata?
von v.

69

Questo:

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

renderà questo:

    <div class="details hide">

ed è il mark-up che voglio.


1
Non mi piace avere la logica nelle viste, anche se è banale, preferisco usare un oggetto ModelView con un metodo getDetailClass ().
BigMike

29
Personalmente preferisco la logica banale, avere un metodo getDetailCssClass significa che il tuo Modello è a conoscenza della tua Vista, abbattendo quell'astrazione. Aggiungerei un metodo HasDetails al modello per ridurre la logica richiesta nella vista, quindi lasciare la logica della classe css nella vista, il che significa che non è necessario sporcare la vista @Model.Details.Count > 0. ad es.<div class="details @(@Model.HasDetails ? "show" : "hide")">
Chris Diver,

26

È possibile aggiungere proprietà al modello come segue:

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

e quindi la tua vista sarà più semplice e non conterrà alcuna logica:

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

Funzionerà anche con molte classi e non renderà la classe se è nulla:

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

con 2 proprietà non null verrà visualizzato:

    <div class="class1 class2"/>

se class1 è null

    <div class=" class2"/>

11
Penso che sia meglio lasciare che la vista definisca cose come le classi css. Ricorda che la vista dovrebbe poter essere modificata in modo chiaro (o addirittura sostituita) senza influire sul modello di vista
tobiak777

1
Sebbene io sia d'accordo con reddy in generale, potrebbero esserci casi in cui può essere giustificato farlo nel modo descritto da Syned. L'ho fatto esattamente così. Nel mio caso mi affido a un oggetto ViewModel pieno di informazioni per il rendering della vista, non è solo un oggetto dati.
Gonzalo Méndez,

1
Lo userei così se ci fossero più di 2 risultati. Ad esempio per 5 possibili classi. Di quanto sarebbe disordinato tenerlo in vista.
Mateusz Migała,

1
La vista è il posto giusto. Formattalo bene come assegnazioni di variabili in un blocco di codice e non sarà disordinato.
Tom Blodget,

3

È possibile utilizzare la funzione String.Format per aggiungere una seconda classe in base alla condizione:

<div class="@String.Format("details {0}", Details.Count > 0 ? "show" : "hide")">
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.