So fügen Sie eine zweite CSS-Klasse mit einem bedingten Wert in Razor MVC 4 hinzu

149

Während Microsoft in Razor MVC4 ein automatisches Rendering von HTML-Attributen erstellt hat, habe ich einige Zeit gebraucht, um herauszufinden, wie eine zweite CSS-Klasse für ein Element basierend auf einem bedingten Rasiererausdruck gerendert werden kann. Ich möchte es mit Ihnen teilen.

Basierend auf einer Modelleigenschaft @ Model.Details möchte ich ein Listenelement ein- oder ausblenden. Wenn es Details gibt, sollte ein div angezeigt werden, andernfalls sollte es ausgeblendet werden. Mit jQuery muss ich lediglich eine Klasseneinstellung bzw. -ausblendung hinzufügen. Für andere Zwecke möchte ich auch eine weitere Klasse hinzufügen, "Details". Mein Aufschlag sollte also sein:

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

Im Folgenden zeige ich einige fehlgeschlagene Versuche (resultierender Aufschlag unter der Annahme, dass keine Details vorhanden sind).

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

wird dies rendern : <div class="details" hide="">.

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

wird dies rendern : <div class=""details" hide&quot;="">.

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

wird dies rendern : <div class="'details" hide&#39;="">.

Keines davon ist korrekt.

R. Schreurs
quelle
Alle Ihre ersten Lösungen hätten funktioniert, wenn Sie sie in eine neue Instanz von MvcHtmlString eingewickelt oder Html.Raw
Kyle

Antworten:

301

Ich glaube, dass es immer noch eine gültige Logik für Ansichten geben kann. Aber für diese Art von Dingen stimme ich @BigMike zu, es ist besser auf dem Modell platziert. Das Problem kann jedoch auf drei Arten gelöst werden:

Ihre Antwort (vorausgesetzt, dies funktioniert, ich habe es nicht versucht):

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

Zweite Option:

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

Dritte Option:

<div class="@("details " + (Model.Details.Count>0 ? "show" : "hide"))">
von v.
quelle
2
Ich habe dies als Antwort akzeptiert, da es mehr Optionen bietet als meine.
R. Schreurs
18
Die 2. Option verursacht den FehlerThe "div" element was not closed
intrepidis
6
Natürlich wird es, wie hier geschrieben, nicht den vollständigen Code geben, sondern den Teil des fraglichen Codes. Wer weiß, wie viele andere Elemente in der div sind;)
von v.
Hat bei mir nicht funktioniert. Ich habe diesen Fehler bekommen'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
Wie hängt Ihr Problem mit der gestellten Frage zusammen?
von v.
69

Dies:

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

wird dies rendern:

    <div class="details hide">

und ist der Aufschlag, den ich will.

R. Schreurs
quelle
1
Ich mag es nicht, Logik in Ansichten zu haben, auch wenn es triviale Logik ist. Ich bevorzuge die Verwendung eines ModelView-Objekts mit einer getDetailClass () -Methode.
BigMike
29
Persönlich bevorzuge ich die triviale Logik. Eine getDetailCssClass-Methode bedeutet, dass Ihr Modell Ihre Ansicht kennt und diese Abstraktion aufschlüsselt. Ich würde dem Modell eine HasDetails-Methode hinzufügen, um die in der Ansicht erforderliche Logik zu reduzieren, und dann die CSS-Klassenlogik der Ansicht überlassen, was bedeutet, dass Sie die Ansicht nicht verunreinigen müssen @Model.Details.Count > 0. zB<div class="details @(@Model.HasDetails ? "show" : "hide")">
Chris Diver
26

Sie können Ihrem Modell wie folgt Eigenschaften hinzufügen:

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

und dann wird Ihre Ansicht einfacher und enthält überhaupt keine Logik:

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

Dies funktioniert auch mit vielen Klassen und rendert keine Klasse, wenn sie null ist:

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

mit 2 nicht null Eigenschaften wird gerendert:

    <div class="class1 class2"/>

wenn class1 null ist

    <div class=" class2"/>
synchronisiert
quelle
11
Ich denke, es ist besser, die Ansicht Dinge wie die CSS-Klassen definieren zu lassen. Denken Sie daran, dass die Ansicht möglicherweise geändert (oder sogar ersetzt) ​​werden kann, ohne dass dies Auswirkungen auf das
Ansichtsmodell hat
1
Obwohl ich Reddy im Allgemeinen zustimme, kann es Fälle geben, in denen es gerechtfertigt sein kann, dies so zu tun, wie es synchronisiert heißt. Ich habe es genau so gemacht. In meinem Fall verlasse ich mich beim Rendern der Ansicht auf ein ViewModel-Objekt voller Informationen, es ist nicht nur ein Datenobjekt.
Gonzalo Méndez
1
Ich würde es so verwenden, wenn es mehr als 2 Ergebnisse gäbe. Zum Beispiel für 5 mögliche Klassen. Dann wäre es chaotisch, es im Blick zu behalten.
Mateusz Migała
1
Die Aussicht ist der richtige Ort. Formatieren Sie es gut als Variablenzuweisungen in einem Codeblock und es wird nicht chaotisch.
Tom Blodget
3

Mit der Funktion String.Format können Sie eine zweite Klasse basierend auf der Bedingung hinzufügen:

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