In play1 erhalte ich normalerweise alle Daten in Aktionen und verwende sie direkt in Ansichten. Da wir die Parameter in der Ansicht nicht explizit deklarieren müssen, ist dies sehr einfach.
Aber in play2 habe ich festgestellt, dass wir alle Parameter (einschließlich request
) im Kopf der Ansichten deklarieren müssen. Es wird sehr langweilig sein, alle Daten in Aktionen zu bekommen und sie in Ansichten zu übergeben.
Wenn ich beispielsweise Menüs anzeigen möchte, die aus der Datenbank auf der Startseite geladen werden, muss ich sie definieren in main.scala.html
:
@(title: String, menus: Seq[Menu])(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Dann muss ich es auf jeder Unterseite deklarieren:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Dann muss ich die Menüs holen und sie weitergeben, um sie bei jeder Aktion anzuzeigen:
def index = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus))
}
def index2 = Action {
val menus = Menu.findAll()
Ok(views.html.index2(menus))
}
def index3 = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus3))
}
Im Moment ist es nur ein Parameter main.scala.html
. Was ist, wenn es viele gibt?
Also entschied ich mich endlich für alle Menu.findAll()
direkt im Blick:
@(title: String)(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-Menu.findAll()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Ich weiß nicht, ob es gut oder empfohlen ist. Gibt es dafür eine bessere Lösung?
quelle
Antworten:
Meiner Meinung nach ist die Tatsache, dass Vorlagen statisch typisiert sind, eine gute Sache: Sie können sicher sein, dass das Aufrufen Ihrer Vorlage beim Kompilieren nicht fehlschlägt.
Es wird jedoch tatsächlich ein Boilerplate auf den aufrufenden Sites hinzugefügt. Aber man kann es reduzieren (ohne statische Typisierung Vorteile zu verlieren).
In Scala sehe ich zwei Möglichkeiten, dies zu erreichen: durch Zusammenstellung von Aktionen oder durch Verwendung impliziter Parameter. In Java empfehle ich, die
Http.Context.args
Map zu verwenden, um nützliche Werte zu speichern und aus den Vorlagen abzurufen, ohne explizit als Vorlagenparameter übergeben zu müssen.Implizite Parameter verwenden
Platzieren Sie den
menus
Parameter am Ende Ihrermain.scala.html
Vorlagenparameter und markieren Sie ihn als "implizit":Wenn Sie nun Vorlagen haben, die diese Hauptvorlage aufrufen, können Sie den
menus
Parametermain
vom Scala-Compiler implizit an die Vorlage übergeben lassen, wenn er auch in diesen Vorlagen als impliziter Parameter deklariert ist:Wenn Sie jedoch möchten, dass es implizit von Ihrem Controller übergeben wird, müssen Sie es als impliziten Wert angeben, der in dem Bereich verfügbar ist, in dem Sie die Vorlage aufrufen. Sie können beispielsweise die folgende Methode in Ihrem Controller deklarieren:
Dann können Sie in Ihren Aktionen einfach Folgendes schreiben:
Weitere Informationen zu diesem Ansatz finden Sie in diesem Blogbeitrag und in diesem Codebeispiel .
Update : Ein schöner Blogeintrag dieses Muster demonstriert hat auch geschrieben worden hier .
Verwenden der Aktionskomposition
Tatsächlich ist es oft nützlich, den
RequestHeader
Wert an die Vorlagen zu übergeben (siehe z . B. dieses Beispiel ). Dadurch wird Ihrem Controller-Code nicht so viel Boilerplate hinzugefügt, da Sie problemlos Aktionen schreiben können, die einen impliziten Anforderungswert erhalten:Da Vorlagen häufig mindestens diesen impliziten Parameter erhalten, können Sie ihn durch einen umfangreicheren Wert ersetzen, der z. B. Ihre Menüs enthält. Sie können das tun , indem Sie die Verwendung von Aktionen Zusammensetzung Mechanismus der Wiedergabe 2.
Dazu müssen Sie Ihre
Context
Klasse definieren und eine zugrunde liegende Anforderung umschließen:Dann können Sie die folgende
ActionWithMenu
Methode definieren :Welches kann so verwendet werden:
Und Sie können den Kontext als impliziten Parameter in Ihren Vorlagen verwenden. ZB für
main.scala.html
:Durch die Verwendung der Aktionskomposition können Sie alle impliziten Werte, die Ihre Vorlagen benötigen, zu einem einzigen Wert zusammenfassen. Andererseits können Sie an Flexibilität verlieren.
Verwenden von Http.Context (Java)
Da Java nicht über den impliziten Mechanismus von Scala oder ähnliches verfügt, können Sie Vorlagenparameter möglicherweise in dem
Http.Context
Objekt speichern, das nur für die Dauer einer Anforderung gültig ist, wenn Sie vermeiden möchten, Vorlagenparameter explizit zu übergeben . Dieses Objekt enthält einenargs
Wert vom TypMap<String, Object>
.Sie können also zunächst einen Interceptor schreiben, wie in der Dokumentation erläutert :
Die statische Methode ist nur eine Abkürzung, um die Menüs aus dem aktuellen Kontext abzurufen. Kommentieren Sie dann Ihren Controller mit dem
Menus
Action Interceptor:Rufen Sie abschließend den
menus
Wert wie folgt aus Ihren Vorlagen ab:quelle
@for(menu <- Menus.current()) {
aberMenus
nie definiert (Sie setzen Menüs (Kleinbuchstaben) :)ctx.args.put("menus", Menu.find.all());
. Gibt es einen Grund? Wie Play, das es in Großbuchstaben umwandelt oder so?Menus
Klasse definiert (der Java-Interceptor). @adis Ja, aber Sie können sie an einem anderen Ort speichern, sogar im Cache.Ich erstelle einfach einen neuen Controller für meine Navigation / mein Menü und rufe ihn aus der Ansicht auf
So können Sie Folgendes definieren
NavController
:nav.scala.html
Dann kann ich das in meiner Hauptansicht so nennen
NavController
:quelle
Ich unterstütze Stians Antwort. Dies ist ein sehr schneller Weg, um Ergebnisse zu erzielen.
Ich habe gerade von Java + Play1.0 auf Java + Play2.0 migriert und die Vorlagen sind der bisher schwierigste Teil. Die beste Möglichkeit, eine Basisvorlage (für Titel, Kopf usw.) zu implementieren, ist die Verwendung von HTTP .Kontext.
Es gibt eine sehr schöne Syntax, die Sie mit Tags erreichen können.
wo get.scala.html ist:
und set.scala.html ist:
bedeutet, dass Sie Folgendes in jede Vorlage schreiben können
Es ist also sehr lesbar und schön.
Dies ist der Weg, den ich gewählt habe. stian - guter rat. Beweist, dass es wichtig ist, nach unten zu scrollen, um alle Antworten zu sehen. :) :)
HTML-Variablen übergeben
Ich habe noch nicht herausgefunden, wie man HTML-Variablen übergibt.
@ (Titel: String, Inhalt: Html)
Ich weiß jedoch, wie ich sie als Block übergeben kann.
@ (Titel: String) (Inhalt: Html)
Vielleicht möchten Sie set.scala.html durch ersetzen
Auf diese Weise können Sie HTML-Blöcke wie folgt übergeben
EDIT: Nebeneffekt bei meiner "Set" -Implementierung
Ein häufiger Anwendungsfall für die Vererbung von Vorlagen in Play.
Sie haben eine base_template.html und dann eine page_template.html, die base_template.html erweitert.
base_template.html könnte ungefähr so aussehen
während die Seitenvorlage ungefähr so aussieht
und dann haben Sie eine Seite (nehmen wir login_page.html an), die aussieht
Das Wichtigste dabei ist, dass Sie "Körper" zweimal einstellen. Einmal in "login_page.html" und dann in "page_template.html".
Es scheint, dass dies einen Nebeneffekt auslöst, solange Sie set.scala.html wie oben vorgeschlagen implementieren.
da die Seite zweimal "login stuff ..." anzeigen würde, weil put den Wert zurückgibt, der beim zweiten Setzen desselben Schlüssels herausspringt. (Siehe Unterschrift in Java-Dokumenten einfügen).
scala bietet eine bessere Möglichkeit, die Karte zu ändern
was diese Nebenwirkung nicht verursacht.
quelle
args
Kontext nach dem Aufruf auf den neuesten Stand zu bringen.Wenn Sie Java verwenden und nur den einfachsten Weg suchen, ohne einen Interceptor schreiben und die Annotation @With verwenden zu müssen, können Sie auch direkt über die Vorlage auf den HTTP-Kontext zugreifen.
Wenn Sie beispielsweise eine Variable benötigen, die aus einer Vorlage verfügbar ist, können Sie sie dem HTTP-Kontext hinzufügen mit:
Sie können dann über die Vorlage darauf zugreifen mit:
Wenn Sie Ihre Methoden mit Http.Context.current (). Args.put ("", "") verunreinigen, ist es natürlich besser, einen Interceptor zu verwenden, aber in einfachen Fällen kann dies den Trick tun.
quelle
Aus Stians Antwort habe ich einen anderen Ansatz versucht. Das funktioniert bei mir.
IM JAVA-CODE
IN HTML TEMPLATE HEAD
UND VERWENDEN WIE
quelle