Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering the Sidebar using the Play Framework

I'm trying to build a common page layout with a main content div and a sidebar with the Play framework:

<html>
<head></head>
<body>
<div id="all">
  <div id="content">the ususal doLayout stuff</div>
  <div id="sidebar">
     <div class="widget">Recent comments...</div>
     <div class="widget">Recent posts...</div>
     other Widgets...
  </div>
</div>
</body>
</html>

Is it possible to render the widgets in the sidebar without preventive binding of the content of the widgets in each controller? Even if there is no such widget in the template, I would have to get all the data required.

I recently used the Lift Framework and could write just <div class="lift:someWidget.news">. This calls the news method in the someWidget class to render the widget. It is possible to retrieve data from the database in that method, so there's no need for preventive binding. Is there something similar in Play to save unnecessary DB queries and unrelated code in the controller?

like image 914
Dave Avatar asked Jan 16 '12 19:01

Dave


2 Answers

Yes. Here are my preferred two options. The right option depends on your particular use case.

Option 1 - Use the @before notation

By using the @before annotation, you can execute common processing on each action that is invoked. It will execute the method before the main action is executed, allowing you to store your data in the renderArgs map, which is the available within the view.

This data in the view can then be access in your main template, and therefore available in all views.

Option 2 - Use AJAX

Put a few divs as placeholders as you have done in your example, and then use the JQuery load that will call an action on your serverside to generate a small piece of HTML just for the snippet that you require.

like image 185
Codemwnci Avatar answered Feb 19 '23 15:02

Codemwnci


You can call a static controller method from a template. Note the @Util - Annotation to tell Play that this is not meant as a action - method:

@Util
public static List<Post> getPosts() { 
    ... 
}

Then call this from your template (perhaps a custom tag):

<div class="widget">
%{ 
    def posts=controllers.Post.getPosts()

    for(post in posts) { 
    }%
        <h2>${post.header}</h2>
        <p>${post.body}</p>
    %{ 
    } 
}% 
</div>

As this is violating the pure MVC-Pattern i would not recommend to use this heavily. But used wisely it can be a really pragmatic solution. And your use-case to build a sidebar in a general layout is perfectly valid usage (in my opinion) - if you later decide to provide a json representation of your data in the main content your layout sidebar is not used - and therefore the data is not fetched when using this pattern.

like image 42
Georg Engel Avatar answered Feb 19 '23 14:02

Georg Engel