Haito
Haito

Reputation: 2069

Working aroung passing an Implicit parameter to every single template

I'm doing some work with PlayFramework templates, but I have encountered a problem. We're using play's helpers which requires Messages (imported from play.api.i18n). Everything was ok until our Designer wanted to have login form in form of Modal... Because it'll be appended to every single template, we'll need to add that messages parameter everywhere - which is ugly IMHO.

Is there a way to work that around? Passing it everywhere would mean that I have to Inject() it everywhere, even if it's needed only to be passed to shut the typechecker.

Sample Page:

@(project: model.Project)(implicit request: Request[AnyContent], messages: Messages)
@main(project.name){
    <h1>@project.name</h1>
    <ul>
    @for(member <- project.members) {
        <li><a href="@routes.UsersController.view(member)">@member</a></li>
    }
    </ul>
}{}

Fragment of Main template:

@(title: String)(content: Html)(additionalImport: Any)(implicit req: Request[AnyContent], messages: Messages)

<!DOCTYPE html>

<html lang="en">
    <head>

    </head>
    <body>
        @* this call actually needs that param. *@ 
        @header.navbar()
        <div class="container">
            @req.flash.get("error").map { error =>
                <div class="flash-error">@error</div>
            }
            @content

        </div>
    </body>
</html>

The Form:

@import model.UserLoginData
@(loginForm: Form[UserLoginData])(implicit req: Request[AnyContent], messages: Messages)
    @helper.form(action = routes.AuthenticationController.login()) {

        @loginForm.globalErrors.map { error =>
            <div class="error">@error.message</div>
        }

        @helper.inputText(loginForm("login"))

        @helper.inputPassword(loginForm("password"))

        <input type="submit" value="Zaloguj"/>
    }
    <a href="@routes.AuthenticationController.recoverForm()">Zapomniałem hasła</a>

Upvotes: 0

Views: 137

Answers (1)

Ilya Posov
Ilya Posov

Reputation: 148

Here I see two work arounds. Unfortunately, I am not able to test them now, but I believe they will both work.

  1. Get rid of the messages parameter from the form template. Use Play.current.injector.instanceOf[MessagesApi] to get MessagesApi implementation just inside the template (here is a question about accessing injector without an @Inject annotation). Then you may call the method preferred(Http.RequestHeader request):Messages to get a Messages instance, and then you need to explicitly pass this to a helper method.
  2. If you just want to get rid of injection and you don't mind passing an implicit messages parameter to every single template, you may implement your own version of the I18nSupport trait. Here I mean that you usually write the controller in the following way: class SomeController @Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport. The messagesApi val overrides the same value of the I18nSupport trait. You may extend this trait with your own MyI18Support trait, and inject MessagesApi inside it (UPD: you may either @Iinject or use Play.current.injector). Then you will only need to write the controller as follows: class SomeController extends Controller with MyI18nSupport.

Upvotes: 1

Related Questions