简体   繁体   English

如何从Play框架中的另一个模板调用一个模板?

[英]How do I invoke a template from another template in Play Framework?

I have a template accountlist.scala.html looking like this: 我有一个模板accountlist.scala.html看起来像这样:

@(accounts: models.domain.AccountList)
@titlebar = {<p>some html</p>}
@content = {
    @for(account <- accounts) {
        <p>@account.name</p>
    }
}

@main(titlebar)(content)

... and another template account.scala.html like this: ...以及另一个模板account.scala.html如下所示:

@(account: models.domain.Account)

@titlebar = {<p>@account.name</p>}
@content = {
    @for(transaction <- account.getTransactions()) {
        <p>@transaction.detail</p>
    }
}
@main(titlebar)(content)

From both of them I am invoking the template main.scala.html . 我从这两个都调用模板main.scala.html

I have access to the entire Account POJO in the first view accountlist.scala.html, so really there is no need for me to invoke the server to get the details of the account when I go to the view in which I display the details. 我可以在第一个视图accountlist.scala.html中访问整个Account POJO,因此,当我进入显示详细信息的视图时,确实不需要调用服务器来获取帐户的详细信息。 I would just like to change view on the client side. 我只想更改客户端的视图。 How could I call the second view account.scala.html from the view accountlist.scala.html a user clicks on an account in the list? 我如何从用户单击列表中的帐户的视图accountlist.scala.html调用第二个视图account.scala.html I am ready to change the templates as needed. 我准备根据需要更改模板。

I have provided a previous answer, which is still available at the end of this post. 我提供了先前的答案,该答案在本文结尾处仍然可用。 From your comments, however I understand that you are asking for something else without understanding how dangerous it is. 但是,从您的评论中,我了解到您在要求其他内容而又不知道它有多危险。

There are three ways of handling your use case, let's start with the worst one. 有三种处理用例的方法,让我们从最差的一种开始。

A stateful web application 有状态的Web应用程序

If you have loaded data into a Pojo from some data source and you want to re-use the Pojo between multiple requests, what you are trying to do is to implement some kind of client-state on the server, such as a cache. 如果您已从某个数据源将数据加载到Pojo中,并且想在多个请求之间重用Pojo,则您要尝试的是在服务器上实现某种客户端状态,例如缓存。 Web applications have been developed in this way for long time and this was the source of major bugs and errors. Web应用程序已经以这种方式开发了很长时间,这是主要错误和错误的来源。 What happens if the underlying account data in the database is updated between one http request and the following? 如果数据库中的基础帐户数据在一个http请求与随后的http请求之间进行更新,会发生什么情况? Your client won't see it, because it use cached data. 您的客户端看不到它,因为它使用了缓存的数据。 Additionally, what happens when the user performs a back in his browser? 此外,当用户在浏览器中执行后退时会发生什么? How do you get notified on the server side so you keep track of where the user is in his navigation flow? 您如何在服务器端收到通知,以便跟踪用户在其导航流程中的位置? For these and others reasons, Play! 由于上述原因和其他原因,请玩! is designed to be stateless . 被设计为无状态的 If you are really into web applications, you probably need to read about what is the REST architectural style. 如果您真的很喜欢Web应用程序,则可能需要阅读什么是REST体系结构样式。

A stateless web application 无状态Web应用程序

In a stateless web applications, you are not allowed to keep data between two http requests, so you have two ways to handle it: 在无状态Web应用程序中,不允许在两个http请求之间保留数据,因此有两种处理方法:

Generate the user interface in a single shot 一次性生成用户界面

This is the approach which you can use when your account data is reduced. 这是减少帐户数据时可以使用的方法。 You embed all the necessary data from each account into your page and you generate the view, which you keep hidden and you show only when the user clicks. 您将每个帐户的所有必要数据嵌入到页面中,并生成视图,该视图保持隐藏状态,仅在用户单击时显示。 Please note that you can generate the HTML on the server side and with Javascript makes only certain part of your DOM visible, or just transfer a JSON representation of your accounts and use some kind of templating library to build the necessary UI directly on the client 请注意,您可以在服务器端生成HTML,并且使用Javascript仅使您的DOM的某些部分可见,或者仅传输帐户的JSON表示并使用某种模板库直接在客户端上构建必要的UI

Generate the user interface when required 必要时生成用户界面

This approach becomes necessary when the account data structure contains too many informations, and you don't want to transfer all this information for all the accounts on the client at first. 当帐户数据结构包含太多信息时,这种方法就变得非常必要,并且您不希望一开始就为客户端上的所有帐户传输所有这些信息。 For example, if you know the user is going to be interested in seeing the details only of very few accounts, you want to require the details only when the user asks for it. 例如,如果您知道用户只对查看很少几个帐户的详细信息感兴趣,那么您只想在用户要求时才需要详细信息。

For example, in your list of accounts you will have a button associated with each account, called details and you will use the account id to send a new request to the server. 例如,在帐户列表中,您将有一个与每个帐户相关联的按钮,称为“详细信息”,您将使用帐户ID向服务器发送新请求。

@(accounts: models.domain.AccountList)
@titlebar = {<p>some html</p>}
@content = {
    @for(account <- accounts) {
        <p>@account.name <button class="details" href="@routes.Controllers.account(account.id)">details</button></p>
    }
}

Please note that you can also generate the user interface on the client side, but you will still need to retrieve it from the server the data structures when the user clicks on the button. 请注意,您还可以在客户端上生成用户界面,但是当用户单击按钮时,仍需要从服务器上检索它的数据结构。 This will ensure that the user retrieves the last available state of the account. 这将确保用户检索帐户的最后可用状态。


Old answer 旧答案

If your goal is to reuse your views, Play views are nothing else then Scala classes, so you can import them: 如果您的目标是重用视图,则Play视图只不过是Scala类,因此可以导入它们:

@import packagename._

and then you use it in another template: 然后在另一个模板中使用它:

@for(account <- accounts) {
        @account(account)
    }

The question reveals a misunderstanding of play framework templates. 这个问题揭示了对游戏框架模板的误解。 When compiling the play project the template code is transformed to html, css and javascript. 编译play项目时,模板代码将转换为html,css和javascript。

You can not "invoke"/link another template showing the account transactions from a href attribute of your Account row. 您无法通过“帐户”行的href属性“调用” /链接另一个显示帐户交易的模板。 However, you can do any of the following: 但是,您可以执行以下任一操作:

  1. In case you have loaded all transactions from all accounts to the client in one go: extend the template to generate separate <div> sections for each account showing the transactions. 如果您一次将所有帐户中的所有交易加载到客户端,请执行以下操作:扩展模板以为显示交易的每个帐户分别生成<div>部分。 Also generate javascript to 1) hide the overview div and 2) show the specific transaction div when clicking on one of the accounts in the overview. 还要生成JavaScript来1)隐藏总览div ,2)单击总览中的一个帐户时显示特定的交易div Please see the knockout library proposed by Edmondo1984 or the accordion or tabs in twitter bootstrap. 请参阅Edmondo1984提出的删除库,或者在twitter bootstrap中查看手风琴或标签。
  2. In case you only load the account overview from the server. 如果仅从服务器加载帐户概览。 Generate a link such as this one href="@routes.Controllers.account(account.id)" (see Edmondo1984 answer) and make another template to view this data. 生成一个这样的链接href="@routes.Controllers.account(account.id)" (请参阅Edmondo1984答案),并制作另一个模板来查看此数据。

Since the question concerned a case in which you got all data from the server, go by option 1. 由于该问题涉及从服务器获取所有数据的情况,请转到选项1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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