Kanımca, şablonların statik olarak yazılmış olması aslında iyi bir şey: derlenirse şablonunuzu çağırmanın başarısız olmayacağı garantidir.
Ancak, gerçekten arayan sitelere bazı standart metinler ekler. Ancak bunu azaltabilirsiniz (statik yazım avantajlarını kaybetmeden).
Scala'da, bunu başarmanın iki yolunu görüyorum: eylem bileşimi yoluyla veya örtük parametreler kullanarak. Java'da,Http.Context.args
yararlı değerleri depolamak ve bunları açık bir şekilde şablon parametreleri olarak geçirmek zorunda kalmadan şablonlardan almak haritayı .
Örtük parametreleri kullanma
Yerleştirin menus
senin sonunda parametreyi main.scala.html
şablon parametreleri ve “örtük” olarak işaretleyin:
@(title: String)(content: Html)(implicit menus: Seq[Menu])
<html>
<head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>
Şimdi, bu ana şablonu çağıran şablonlarınız varsa, parametrenin, bu şablonlarda da örtük bir parametre olarak bildirilmesi durumunda Scala derleyicisi tarafından şablona menus
örtük olarak iletilmesini sağlayabilirsiniz main
:
@()(implicit menus: Seq[Menu])
@main("SubPage") {
...
}
Ancak, denetleyicinizden örtük olarak aktarılmasını istiyorsanız, şablonu çağırdığınız kapsamda bulunan örtük bir değer olarak sağlamanız gerekir. Örneğin, denetleyicinizde aşağıdaki yöntemi bildirebilirsiniz:
implicit val menu: Seq[Menu] = Menu.findAll
Ardından, eylemlerinizde yalnızca aşağıdakileri yazabileceksiniz:
def index = Action {
Ok(views.html.index())
}
def index2 = Action {
Ok(views.html.index2())
}
Bu yaklaşımla ilgili daha fazla bilgiyi bu blog gönderisinde ve bu kod örneğinde bulabilirsiniz .
Güncelleme : Bu kalıbı gösteren güzel bir blog yazısı da burada yazılmıştır .
İşlem kompozisyonunu kullanma
Aslında, RequestHeader
değeri şablonlara aktarmak genellikle yararlıdır (örneğin, bu örneğe bakın ). Bu, denetleyici kodunuza çok fazla standart şablon eklemez çünkü örtük bir istek değeri alan eylemleri kolayca yazabilirsiniz:
def index = Action { implicit request =>
Ok(views.html.index()) // The `request` value is implicitly passed by the compiler
}
Bu nedenle, şablonlar genellikle en azından bu örtük parametreyi aldığından, onu örneğin menülerinizi içeren daha zengin bir değerle değiştirebilirsiniz. Bunu Play 2'nin eylem oluşturma mekanizmasını kullanarak yapabilirsiniz .
Bunu yapmak için Context
sınıfınızı tanımlamanız ve temel bir isteği sarmalamanız gerekir:
case class Context(menus: Seq[Menu], request: Request[AnyContent])
extends WrappedRequest(request)
Ardından aşağıdaki ActionWithMenu
yöntemi tanımlayabilirsiniz :
def ActionWithMenu(f: Context => Result) = {
Action { request =>
f(Context(Menu.findAll, request))
}
}
Hangisi şu şekilde kullanılabilir:
def index = ActionWithMenu { implicit context =>
Ok(views.html.index())
}
Ve bağlamı şablonlarınızda örtük bir parametre olarak alabilirsiniz. Örneğin main.scala.html
:
@(title: String)(content: Html)(implicit context: Context)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu <- context.menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>
Eylem bileşimini kullanmak, şablonlarınızın gerektirdiği tüm örtük değerleri tek bir değerde toplamanıza olanak tanır, ancak diğer yandan biraz esnekliği kaybedebilirsiniz ...
Http.Context (Java) Kullanma
Java, Scala'nın implicits mekanizmasına veya benzerine sahip olmadığından, şablon parametrelerini açık bir şekilde iletmekten kaçınmak istiyorsanız, olası bir yol onları Http.Context
yalnızca bir istek süresince yaşayan nesnede saklamaktır . Bu nesne bir tür args
değeri içerir Map<String, Object>
.
Böylece, dokümantasyonda açıklandığı gibi bir engelleyici yazarak başlayabilirsiniz :
public class Menus extends Action.Simple {
public Result call(Http.Context ctx) throws Throwable {
ctx.args.put("menus", Menu.find.all());
return delegate.call(ctx);
}
public static List<Menu> current() {
return (List<Menu>)Http.Context.current().args.get("menus");
}
}
Statik yöntem, menüleri mevcut bağlamdan almak için sadece bir kısaltmadır. Ardından, Menus
eylem durdurucu ile karıştırılması için denetleyicinize açıklama ekleyin :
@With(Menus.class)
public class Application extends Controller {
// …
}
Son olarak, menus
değeri şablonlarınızdan aşağıdaki gibi alın:
@(title: String)(content: Html)
<html>
<head><title>@title</title></head>
<body>
<div>
@for(menu <- Menus.current()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body>
</html>