मेरी राय में, यह तथ्य कि टेम्प्लेट सांख्यिकीय रूप से टाइप किए जाते हैं, वास्तव में एक अच्छी बात है: आप गारंटी देते हैं कि आपका टेम्प्लेट कॉल करना विफल नहीं होगा यदि यह संकलित होता है।
हालांकि, यह वास्तव में कॉलिंग साइटों पर कुछ बॉयलरप्लेट जोड़ता है। लेकिन आप इसे कम कर सकते हैं (स्थैतिक टाइपिंग के फायदे खोए बिना)।
स्काला में, मैं इसे प्राप्त करने के दो तरीके देखता हूं: क्रिया रचना के माध्यम से या अंतर्निहित मापदंडों का उपयोग करके। जावा में मैं Http.Context.args
उपयोगी मानों को संग्रहीत करने के लिए मानचित्र का उपयोग करने का सुझाव देता हूं और उन्हें टेम्पलेट्स मापदंडों के रूप में स्पष्ट रूप से पारित किए बिना टेम्पलेट्स से पुनर्प्राप्त करता हूं।
अंतर्निहित मापदंडों का उपयोग करना
जगह menus
अपने के अंत में पैरामीटर main.scala.html
टेम्पलेट मापदंडों और "के रूप में निहित" में चिह्नित:
@(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>
अब यदि आपके पास इस मुख्य टेम्प्लेट को कॉल करने के लिए टेम्पलेट हैं, तो आपके पास स्केल कम्पाइलर द्वारा टेम्पलेट के menus
लिए अंतर्निहित रूप से उत्तीर्ण किया जा सकता है main
यदि यह इन टेम्प्लेट में एक अंतर्निहित पैरामीटर के रूप में घोषित किया गया है:
@()(implicit menus: Seq[Menu])
@main("SubPage") {
...
}
लेकिन अगर आप चाहते हैं कि यह आपके नियंत्रक से अंतर्निहित रूप से पारित हो जाए तो आपको इसे एक निहित मूल्य के रूप में प्रदान करने की आवश्यकता है, जहां से आप टेम्पलेट कहते हैं, उस दायरे में उपलब्ध हैं। उदाहरण के लिए, आप अपने नियंत्रक में निम्न विधि की घोषणा कर सकते हैं:
implicit val menu: Seq[Menu] = Menu.findAll
फिर अपने कार्यों में आप बस निम्नलिखित लिख सकेंगे:
def index = Action {
Ok(views.html.index())
}
def index2 = Action {
Ok(views.html.index2())
}
आप इस ब्लॉग पोस्ट और इस कोड नमूने में इस दृष्टिकोण के बारे में अधिक जानकारी पा सकते हैं ।
अपडेट : इस पैटर्न को प्रदर्शित करने वाला एक अच्छा ब्लॉग पोस्ट भी यहां लिखा गया है ।
क्रिया रचना का उपयोग करना
वास्तव में, अक्सर RequestHeader
वैल्यू को टेम्प्लेट में पास करना उपयोगी होता है (उदाहरण के लिए यह नमूना देखें )। यह आपके नियंत्रक कोड में इतनी बॉयलरप्लेट नहीं जोड़ता है क्योंकि आप आसानी से एक अंतर्निहित अनुरोध मान प्राप्त करने वाले कार्यों को लिख सकते हैं:
def index = Action { implicit request =>
Ok(views.html.index()) // The `request` value is implicitly passed by the compiler
}
इसलिए, चूंकि टेम्पलेट अक्सर कम से कम इस निहित पैरामीटर को प्राप्त करते हैं, आप इसे अपने मेनू जैसे अमीर मूल्य के साथ बदल सकते हैं। आप प्ले 2 की क्रिया रचना तंत्र का उपयोग करके ऐसा कर सकते हैं ।
ऐसा करने के लिए आपको अपनी Context
कक्षा को परिभाषित करना होगा , अंतर्निहित अनुरोध को लपेटकर:
case class Context(menus: Seq[Menu], request: Request[AnyContent])
extends WrappedRequest(request)
तो आप निम्न ActionWithMenu
विधि को परिभाषित कर सकते हैं :
def ActionWithMenu(f: Context => Result) = {
Action { request =>
f(Context(Menu.findAll, request))
}
}
जिसका उपयोग इस तरह किया जा सकता है:
def index = ActionWithMenu { implicit context =>
Ok(views.html.index())
}
और आप संदर्भ को अपने टेम्प्लेट में एक अंतर्निहित पैरामीटर के रूप में ले सकते हैं। जैसे 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>
क्रिया रचना का उपयोग करने से आप उन सभी निहित मूल्यों को एकत्र कर सकते हैं, जिनके लिए आपके टेम्पलेट्स को एक ही मूल्य की आवश्यकता होती है, लेकिन दूसरी ओर आप कुछ नुकसान भी कर सकते हैं ...
Http.Context (Java) का उपयोग करना
चूँकि जावा में स्काला का इम्पैक्टस मैकेनिज़्म या समान नहीं है, यदि आप स्पष्ट रूप से टेंपलेट्स मापदंडों से बचना चाहते हैं तो एक संभावित तरीका उन्हें उस Http.Context
ऑब्जेक्ट में संग्रहीत करना है जो केवल अनुरोध की अवधि के लिए रहता है। इस ऑब्जेक्ट में args
प्रकार का मान है Map<String, Object>
।
इस प्रकार, आप एक इंटरसेप्टर लिखकर शुरू कर सकते हैं, जैसा कि प्रलेखन में बताया गया है :
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");
}
}
स्थैतिक विधि वर्तमान संदर्भ से मेनू को पुनः प्राप्त करने के लिए सिर्फ एक आशुलिपि है। फिर अपने कंट्रोलर को Menus
एक्शन इंटरसेप्टर के साथ मिलाने के लिए एनोटेट करें :
@With(Menus.class)
public class Application extends Controller {
// …
}
अंत में, menus
अपने टेम्प्लेट से मूल्य इस प्रकार प्राप्त करें:
@(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>