scalaplayframework-2.2scala-template

Dynamically change (@main) name, in Play Framework 2.2.2 (Scala)


I was trying to make the Play layout a bit more dynamic, but didn't know how, any help??

My problem goes like :

index.scala.html

@(title: String,templateName:String) // templateName is data obtained from a db src,  

@templates.(@templateName)(title,templateName){ // I wanted to put value of templateName after @template.****, so that template names get set at compile time, but of course it gives out errors
}

Inside view -> templates -> main.scala.html, foo.scala.html, bar.scala.html

I am not saying that I need to make the whole 'Main-Layout' dynamically but, just get the names dynamically. Can it be done??

I tried doing it like below, but I will need to know every templates name, any suggestions

index.scala.html

@(title: String,templateName:String)

@if(templateName == "foo"){
    @templates.foo(title,templateName){
    }
}
else if(templateName == "bar"){
    @templates.bar(title,templateName){
} else {
    ......
}

I guess I didn't explain my issue properly:

@johanandren Well there seems to be some misunderstanding. Yes I do understand now that I am not allowed to give template name dynamically (if reflection isn't used, and it seems to have its own cons as well,thanks to you and @Khanser)from the controller, which I never was planning to do at all.

But like you have said "If you just want to apply common templating around your individual sub-templates", my main concern is that I wont have a common templating, as you have stated , infact based on the user => different main template. Yes I could use the switch/case for my purpose but I'll need to know * template names and hardcode them on each and every sub-template.

And Yes, I have understood the use of "templates->main.scala.html" and "sub-templates=>index.scala.html" etc,etc.... and injecting sub-templates on main templates. And I think I have already been doing this invert the template flow.


Solution

  • Each template gets compiled into a class with one method, calling the template is not dynamic but just like calling any other method/function in Scala or Java. Making this dynamic is possible using reflection but you will loose the static type check that ensures that you will get a compiler error if you try to call a template that does not exist or use parameters that does not match the parameter list of the individual template.

    There might some use cases where you absolutely need this kind of dynamic template handling (like if you select which template to use with a database flag) but the way you have done it with an if else, or more concisely using a Scala switch/match, is probably the best since you get explicit code that will fail to compile if you do it wrong, as opposed to reflection stuff that wouldn't fail until runtime when that specific template was used.

    If you just want to apply common templating around your individual sub-templates, the same header for example, then the common way to do this is to invert the template flow so that each individual template will call a "main" template passing their content as a HTML parameter that the main template will incude in the common structure.

    This is how the sample play project templates are setup when you create a new project, so you can look at that, index.scala.html will call main.scala.html which contains the common markup.