Changing the layout template at runtime

In Kohana (the PHP framework), a layout is implemented through Template_Controller, which continues a member variable called $ template, which serves as a layout view. Then, in the action method, you can populate $ template with additional submenus, usually a representation of the content. ( http://forum.kohanaframework.org/discussion/3612/kohana-layout-system/p1 )

This allows me to change the theme layout at runtime. This is useful for a multi-tasking system where the tenant can choose his own theme (two columns, three columns, etc.).

How can I achieve this in playframework 2 Scala, with the Scala template engine? In other words, I would like to have several layout templates in which the tenant can choose. The controller then displays the layout template and content template for the specific action.

Something like (pseudo action code of a controller):

  • Based on the user, find the layout theme (the name stored in the row in the database and the corresponding mapping display file).
  • Display the content view of a specific action.
  • Render layout view obtained from (1) together with (2).

Note. For each action, the layout theme can change for each user, but the content remains the same.

It has documentation ( http://www.playframework.com/documentation/2.1.1/ScalaTemplateUseCases )
the content template, say index.scala.html, includes a call to main, which is defined in main.scala.html, the layout template. In other words, it is hard-coded, so index.scala.html is closely related to main.scala.html.

I want to talk about the main thing from the controller using reflection, and then transfer the contents.

An alternative would be to use an interpreted template engine such as Scalate.

Any suggestion?

+6
source share
1 answer

I see 2 options to accomplish what you need. The first would be to pass the theme parameter to your templates (for example, something to tell the called template which theme / layout to use) and use this parameter to conditionally call the layout template. The second way is to process the condition inside the controller by returning the corresponding view based on the selected topic.

Option 1

In your action, you will want to pass some value to your template to indicate which theme to use.

def index = Action { Ok(views.html.index("two-col")) } 

Then in your index.scala.html you would do something like this:

 @(theme: String) @content = { <h1>Action Specific Content</h1> } @if("two-col" eq theme) { @twoCol("title")(content) } else { @main("title")(content) } 

This assumes that there is a twoCol.scala.html template, for example:

 @(title: String)(content: Html) <!DOCTYPE html> <html> ... <body> <h1>Two Column</h1> @content </body> </html> 

Note. You can also pass the topic using an implicit parameter, see this SO question . This will make it easier to explicitly pass the template for each rendering.

Option 2

It would be as simple as the following in your controller, but would probably require much more repetitive code in presentation templates.

 def index = Action { var theme = ... ... if (theme eq 'tow-col') { Ok(views.html.twocol.index("two-col")) } else { Ok(views.html.default.index()) } 

It is assumed that the twocol and default package in /app/views has index.scala.html .

Additional comments

As you can tell from option 1, index.scala.html is not closely related to main.scala.html. You can replace the call with the main one with a call to any other template or even without a template.

FWIW, I would go with option 1, and it would probably turn into a better solution.

+2
source

Source: https://habr.com/ru/post/947990/


All Articles