简体   繁体   中英

Play Framework / Twirl Dynamically include templates

Use case: I have a route handling all requests at host:port/p route looks like the following:

GET     /p/*path    controllers.Application.p(path: String)

The p method gets some data and passes it right through to the view p :

return ok(p.render(currentSession));

In the view I want to import a template if there exists one that matches a String in my passed data. In this case the String represents a model object name such as "User" and if there is a matching template it would be views/custompages/User.scala.html . If there is no matching template, I would like to use a generic one such as views/generic.scala.html .

I have 2 parts to the question:

Part 1 : I see that I can check for a template existence simply by doing the following:

@if(custompages.User != null) {
    <p>it exists!</p>
}

but if i change it to custompages.Usera (a non existent template) I get a compilation error ( object Usera is not a member of package ). How can do this check?

Part 2 : How can I do the check using the String I have representing the model class? concatenating it in the place of the hard coded "User" in the answer to part 1?

Am I going about this the wrong way? Is what I am doing supposed to be handled in the controller using reflection to look for the matching template then render the appropriate one?

I decided to work the problem from the controller instead of the view. This is the code I used to do it in case anyone else ends up here looking for a similar answer.

notes: The associatedEntity is how I am determining which template to render I am invoking the class render and passing my own session object as parameter I used the following to help create the answer: Play framework 2.1.3 function that will render scala template with given parameters

Thank you @biesior for the suggestion!

public Result p(String uri) {

    Session currentSession = getSession();

    final Class<?> clazz;
    try {
        clazz = Class.forName("com.domain.views.html." + currentSession.currentPage.associatedEntity.getSimpleName());

        //assumed you have a String parameter for your template
        java.lang.reflect.Method render = null;
        try {
            render = clazz.getDeclaredMethod("render", Session.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        play.twirl.api.Html html = null;
        try {
            html = (play.twirl.api.Html) render.invoke(null, currentSession);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return ok(html);
    } catch (ClassNotFoundException e) {
        return ok(p.render(currentSession));
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM