W play1 zwykle otrzymuję wszystkie dane w akcjach, używam ich bezpośrednio w widokach. Ponieważ nie musimy jawnie deklarować parametrów w widoku, jest to bardzo łatwe.
Ale w play2 stwierdziłem, że musimy zadeklarować wszystkie parametry (w tym request
) w nagłówku widoków, bardzo nudne będzie pobranie wszystkich danych w akcjach i przekazanie ich do widoków.
Na przykład, jeśli chcę wyświetlić menu, które są ładowane z bazy danych na stronie głównej, muszę to zdefiniować w 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>
Następnie muszę to zadeklarować na każdej podstronie:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Następnie muszę zdobyć menu i przekazać je do wyświetlenia w każdej akcji:
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))
}
Na razie to tylko jeden parametr main.scala.html
, a jeśli jest ich wiele?
W końcu zdecydowałem się wszystko Menu.findAll()
bezpośrednio na widoku:
@(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>
Nie wiem, czy jest to dobre, czy zalecane, czy jest na to lepsze rozwiązanie?
źródło
Odpowiedzi:
Moim zdaniem fakt, że szablony są typowane statycznie, jest w rzeczywistości dobrą rzeczą: masz gwarancję, że wywołanie szablonu nie zakończy się niepowodzeniem, jeśli się skompiluje.
Jednak rzeczywiście dodaje pewne standardowe elementy do stron wywołujących. Ale możesz to zmniejszyć (bez utraty zalet pisania statycznego).
W Scali widzę dwa sposoby osiągnięcia tego: poprzez kompozycję akcji lub użycie niejawnych parametrów. W Javie sugeruję użycie
Http.Context.args
mapy do przechowywania przydatnych wartości i pobierania ich z szablonów bez konieczności jawnego przekazywania jako parametrów szablonów.Używanie niejawnych parametrów
Umieść
menus
parametr na końcumain.scala.html
parametrów szablonu i oznacz go jako „niejawny”:Teraz, jeśli masz szablony wywołujące ten główny szablon, możesz mieć
menus
parametr niejawnie przekazany domain
szablonu przez kompilator Scala, jeśli jest on również zadeklarowany jako niejawny parametr w tych szablonach:Ale jeśli chcesz, aby była ona niejawnie przekazywana z kontrolera, musisz podać ją jako niejawną wartość, dostępną w zakresie, z którego wywołujesz szablon. Na przykład możesz zadeklarować w kontrolerze następującą metodę:
Następnie w swoich działaniach będziesz mógł po prostu napisać:
Więcej informacji na temat tego podejścia można znaleźć w tym poście na blogu oraz w tym przykładzie kodu .
Aktualizacja : ładny wpis na blogu demonstrujący ten wzór został również napisany tutaj .
Używanie kompozycji akcji
W rzeczywistości często przydatne jest przekazywanie
RequestHeader
wartości do szablonów (patrz np. Ten przykład ). Nie dodaje to zbyt wiele schematu do kodu kontrolera, ponieważ można łatwo pisać akcje otrzymujące niejawną wartość żądania:Tak więc, ponieważ szablony często otrzymują przynajmniej ten niejawny parametr, możesz zastąpić go bogatszą wartością zawierającą np. Twoje menu. Możesz to zrobić za pomocą mechanizmu kompozycji akcji Play 2.
Aby to zrobić, musisz zdefiniować swoją
Context
klasę, opakowując podstawowe żądanie:Następnie możesz zdefiniować następującą
ActionWithMenu
metodę:Które można wykorzystać w ten sposób:
I możesz wziąć kontekst jako niejawny parametr w swoich szablonach. Np. Dla
main.scala.html
:Korzystanie z kompozycji akcji umożliwia agregowanie wszystkich niejawnych wartości wymaganych przez szablony w jedną wartość, ale z drugiej strony możesz stracić pewną elastyczność…
Korzystanie z Http.Context (Java)
Ponieważ Java nie ma mechanizmu implicits Scala lub podobnego, jeśli chcesz uniknąć jawnego przekazywania parametrów szablonów, możliwym sposobem jest przechowywanie ich w
Http.Context
obiekcie, który istnieje tylko na czas trwania żądania. Ten obiekt zawieraargs
wartość typuMap<String, Object>
.Dlatego możesz zacząć od napisania przechwytywacza, jak wyjaśniono w dokumentacji :
Metoda statyczna to tylko skrót do pobierania menu z bieżącego kontekstu. Następnie dodaj adnotację do kontrolera, który ma zostać zmieszany z
Menus
przechwytywaczem akcji:Na koniec pobierz
menus
wartość ze swoich szablonów w następujący sposób:źródło
@for(menu <- Menus.current()) {
aleMenus
nigdy nie jest zdefiniowany (umieszczasz menu (małe litery)ctx.args.put("menus", Menu.find.all());
:). Czy jest powód? Lubisz Play, który przekształca to w wielkie litery, czy coś?Menus
zdefiniowana klasa (przechwytywacz Java). @adis Tak, ale możesz przechowywać je w innym miejscu, nawet w pamięci podręcznej.Sposób, w jaki to robię, polega po prostu na utworzeniu nowego kontrolera dla mojej nawigacji / menu i wywołaniu go z widoku
Możesz więc zdefiniować swoje
NavController
:nav.scala.html
W moim głównym widoku mogę to nazwać
NavController
:źródło
Popieram odpowiedź Stiana. To bardzo szybki sposób na uzyskanie wyników.
Właśnie przeprowadziłem migrację z Java + Play1.0 do Java + Play2.0, a szablony są jak dotąd najtrudniejszą częścią, a najlepszym sposobem, w jaki znalazłem zaimplementowanie szablonu podstawowego (dla tytułu, nagłówka itp.), Jest użycie Http .Kontekst.
Istnieje bardzo ładna składnia, którą można uzyskać za pomocą tagów.
gdzie get.scala.html to:
a set.scala.html to:
oznacza, że możesz napisać w dowolnym szablonie
Jest więc bardzo czytelny i ładny.
To jest droga, którą wybrałem. stian - dobra rada. Dowodzi, że przewijanie w dół, aby zobaczyć wszystkie odpowiedzi, jest ważne. :)
Przekazywanie zmiennych HTML
Nie wymyśliłem jeszcze, jak przekazywać zmienne HTML.
@ (tytuł: String, treść: Html)
jednak wiem, jak przekazać je jako blok.
@ (tytuł: String) (zawartość: Html)
więc możesz zamienić set.scala.html na
w ten sposób możesz przekazywać bloki HTML w ten sposób
EDYCJA: Efekt uboczny mojej implementacji „zestawu”
Typowe dziedziczenie szablonów IT w Play.
Masz plik base_template.html, a następnie page_template.html, który rozszerza base_template.html.
base_template.html może wyglądać mniej więcej tak
podczas gdy szablon strony może wyglądać jak
a następnie masz stronę (załóżmy login_page.html), która wygląda jak
Ważną rzeczą do zapamiętania jest dwukrotne ustawienie „body”. Raz w „login_page.html”, a następnie w „page_template.html”.
Wygląda na to, że wywołuje to efekt uboczny, o ile implementujesz set.scala.html, jak zasugerowałem powyżej.
tak jak strona pokaże dwukrotnie "login stuff ...", ponieważ polecenie put zwraca wartość, która pojawia się przy drugim umieszczeniu tego samego klucza. (zobacz umieszczanie podpisu w dokumentach java).
scala zapewnia lepszy sposób modyfikowania mapy
który nie powoduje tego efektu ubocznego.
źródło
args
po wywołaniu kontekstu jako bieżący.Jeśli używasz Javy i chcesz po prostu jak najprostszy sposób bez konieczności pisania przechwytywacza i używania adnotacji @With, możesz również uzyskać dostęp do kontekstu HTTP bezpośrednio z szablonu.
Np. Jeśli potrzebujesz zmiennej dostępnej z szablonu, możesz dodać ją do kontekstu HTTP za pomocą:
Następnie możesz uzyskać do niego dostęp z szablonu za pomocą:
Oczywiście, jeśli zaśmiecasz swoje metody za pomocą Http.Context.current (). Args.put ("", ""), lepiej jest użyć przechwytywacza, ale w prostych przypadkach może to załatwić sprawę.
źródło
Z odpowiedzi Stiana, spróbowałem innego podejścia. To działa dla mnie.
W KODZIE JAVA
W nagłówku szablonu HTML
I UŻYWAJ JAK
źródło