Jak dodać drugą klasę CSS z wartością warunkową w Razor MVC 4


149

Podczas gdy Microsoft stworzył pewne automagiczne renderowanie atrybutów HTML w maszynce do golenia MVC4, zajęło mi trochę czasu, zanim dowiedziałem się, jak wyrenderować drugą klasę css na elemencie, w oparciu o warunkowe wyrażenie maszynki do golenia. Chciałbym się z wami tym podzielić.

Opierając się na właściwości modelu @ Model.Details, chcę pokazać lub ukryć element listy. Jeśli istnieją szczegóły, należy wyświetlić element div, w przeciwnym razie powinien zostać ukryty. Korzystając z jQuery, wszystko, co muszę zrobić, to dodać odpowiednio klasę show lub hide. Z innych powodów chcę również dodać kolejną klasę, „szczegóły”. Tak więc moja marża powinna wynosić:

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

Poniżej przedstawiam kilka nieudanych prób (wynikający z marży przy założeniu, że nie ma szczegółów).

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

uczyni to: <div class="details" hide="">.

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

uczyni to: <div class=""details" hide&quot;="">.

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

uczyni to: <div class="'details" hide&#39;="">.

Żadne z nich nie są poprawnymi marżami.


Wszystkie twoje pierwsze rozwiązania zadziałałyby, gdybyś zapakował je w nową instancję MvcHtmlString lub użył Html.Raw
Kyle.

Odpowiedzi:


301

Uważam, że w poglądach wciąż może istnieć i ważna logika. Ale na tego typu rzeczy zgadzam się z @BigMike, lepiej jest umieścić go na modelu. Powiedziawszy, że problem można rozwiązać na trzy sposoby:

Twoja odpowiedź (zakładając, że to działa, nie próbowałem tego):

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

Druga opcja:

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

Trzecia opcja:

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

2
Przyjąłem to jako odpowiedź, ponieważ oferuje więcej opcji niż moja.
R. Schreurs

18
Druga opcja powoduje błądThe "div" element was not closed
intrepidis

6
Oczywiście będzie tak, ponieważ to, co tu napisano, nie jest pełnym kodem, ale raczej jego częścią, o której mowa. Kto wie, ile innych elementów jest w div;)
von v.

Nie działa dla mnie. Mam ten błąd'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

Jaki jest związek Twojego problemu z opublikowanym pytaniem?
von v.

69

To:

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

wyrenderuje to:

    <div class="details hide">

i to jest narzut, którego chcę.


1
Nie lubię mieć logiki w widokach, nawet jeśli jest to logika trywialna, wolę używać obiektu ModelView z metodą getDetailClass ().
BigMike

29
Osobiście wolę trywialną logikę, posiadanie metody getDetailCssClass oznacza, że ​​Twój Model jest świadomy Twojego Widoku, przełamując tę ​​abstrakcję. Dodałbym metodę HasDetails do Modelu, aby zmniejszyć logikę wymaganą w widoku, a następnie pozostawiłbym logikę klasy css w widoku, co oznacza, że ​​nie musisz zaśmiecać widoku@Model.Details.Count > 0 . np.<div class="details @(@Model.HasDetails ? "show" : "hide")">
Chris Diver

26

Możesz dodać właściwość do swojego modelu w następujący sposób:

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

a wtedy twój widok będzie prostszy i nie będzie zawierał żadnej logiki:

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

To zadziała nawet z wieloma klasami i nie wyrenderuje klasy, jeśli jest pusta:

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

z 2 niezerowymi właściwościami wyrenderuje:

    <div class="class1 class2"/>

jeśli class1 ma wartość null

    <div class=" class2"/>

11
Myślę, że lepiej jest pozwolić widokowi zdefiniować takie rzeczy, jak klasy css. Pamiętaj, że widok powinien móc być głęboko modyfikowany (lub nawet zastępowany) bez wpływu na model widoku
tobiak777

1
Chociaż ogólnie zgadzam się z reddy, mogą wystąpić przypadki, w których można to zrobić tak, jak mówi syned. Zrobiłem to dokładnie w ten sposób. W moim przypadku polegam na obiekcie ViewModel pełnym informacji do renderowania widoku, nie jest to tylko obiekt danych.
Gonzalo Méndez

1
Użyłbym tego w ten sposób, gdyby było więcej niż 2 wyniki. Na przykład na 5 możliwych zajęć. Niż byłoby niechlujnie trzymać to na widoku.
Mateusz Migała

1
Widok jest we właściwym miejscu. Sformatuj go ładnie jako przypisania zmiennych w bloku kodu i nie będzie bałaganu.
Tom Blodget

3

Możesz użyć funkcji String.Format, aby dodać drugą klasę na podstawie warunku:

<div class="@String.Format("details {0}", Details.Count > 0 ? "show" : "hide")">
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.