No play1, eu costumo obter todos os dados em ações, usá-los diretamente nas visualizações. Como não precisamos declarar explicitamente parâmetros à vista, isso é muito fácil.
Mas no play2, descobri que temos que declarar todos os parâmetros (inclusive request
) no cabeçalho das visualizações, será muito chato obter todos os dados em ações e passá-los para as visualizações.
Por exemplo, se eu precisar exibir menus carregados do banco de dados na primeira página, preciso defini-lo em main.scala.html
:
@(title: String, menus: Seq[Menu])(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-menus) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Então eu tenho que declarar em todas as subpáginas:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Então eu tenho que pegar os menus e passá-lo para ver em todas as ações:
def index = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus))
}
def index2 = Action {
val menus = Menu.findAll()
Ok(views.html.index2(menus))
}
def index3 = Action {
val menus = Menu.findAll()
Ok(views.html.index(menus3))
}
Por enquanto main.scala.html
, existe apenas um parâmetro , e se houver muitos?
Então, finalmente, eu decidi todos Menu.findAll()
diretamente em vista:
@(title: String)(content: Html)
<html><head><title>@title</title></head>
<body>
<div>
@for(menu<-Menu.findAll()) {
<a href="#">@menu.name</a>
}
</div>
@content
</body></html>
Não sei se é bom ou recomendado, existe alguma solução melhor para isso?
fonte
Respostas:
Na minha opinião, o fato de que os modelos são estaticamente digitados é realmente uma coisa boa : você garante que a chamada do seu modelo não falhará se for compilada.
No entanto, ele realmente adiciona alguns clichês nos sites de chamada. Mas você pode reduzi-lo (sem perder as vantagens da digitação estática).
No Scala, vejo duas maneiras de alcançá-lo: através da composição de ações ou usando parâmetros implícitos. Em Java, sugiro usar o
Http.Context.args
mapa para armazenar valores úteis e recuperá-los dos modelos sem ter que passar explicitamente como parâmetros de modelos.Usando parâmetros implícitos
Coloque o
menus
parâmetro no final dosmain.scala.html
parâmetros do seu modelo e marque-o como "implícito":Agora, se você tiver modelos chamando esse modelo principal, poderá
menus
passar o parâmetro implicitamente para omain
modelo pelo compilador Scala, se ele também for declarado como parâmetro implícito nesses modelos:Mas se você deseja que seja passado implicitamente do seu controlador, é necessário fornecê-lo como um valor implícito, disponível no escopo de onde você chama o modelo. Por exemplo, você pode declarar o seguinte método no seu controlador:
Em suas ações, você poderá escrever o seguinte:
Você pode encontrar mais informações sobre essa abordagem nesta postagem do blog e neste exemplo de código .
Atualização : Um bom post de blog demonstrando esse padrão também foi escrito aqui .
Usando composição de ações
Na verdade, geralmente é útil passar o
RequestHeader
valor para os modelos (veja, por exemplo, este exemplo ). Isso não adiciona muito clichê ao código do controlador, porque você pode escrever facilmente ações que recebem um valor implícito de solicitação:Portanto, como os modelos geralmente recebem pelo menos esse parâmetro implícito, você pode substituí-lo por um valor mais rico, contendo, por exemplo, seus menus. Você pode fazer isso usando o mecanismo de composição de ações do Play 2.
Para fazer isso, você precisa definir sua
Context
classe, agrupando uma solicitação subjacente:Então você pode definir o seguinte
ActionWithMenu
método:Que pode ser usado assim:
E você pode considerar o contexto como um parâmetro implícito em seus modelos. Por exemplo, para
main.scala.html
:O uso da composição de ações permite agregar todos os valores implícitos que seus modelos exigem em um único valor, mas por outro lado, você pode perder alguma flexibilidade…
Usando Http.Context (Java)
Como o Java não possui o mecanismo implícito do Scala ou similar, se você deseja evitar passar explicitamente os parâmetros dos modelos, uma maneira possível é armazená-los no
Http.Context
objeto que vive apenas pela duração de uma solicitação. Este objecto contém umargs
valor de tipoMap<String, Object>
.Assim, você pode começar escrevendo um interceptador, conforme explicado na documentação :
O método estático é apenas uma abreviação para recuperar os menus do contexto atual. Em seguida, anote seu controlador para ser misturado com o
Menus
interceptor de ação:Por fim, recupere o
menus
valor dos seus modelos da seguinte maneira:fonte
@for(menu <- Menus.current()) {
masMenus
nunca é definido (você coloca menus (em letras minúsculas)ctx.args.put("menus", Menu.find.all());
:). Há uma razão? Como o Play que o transforma em maiúsculas ou algo assim?Menus
classe definida (o interceptor Java). @adis Sim, mas você pode armazená-los em outro local, mesmo no cache.A maneira como faço isso é apenas criar um novo controlador para a minha navegação / menu e chamá-lo da exibição
Então você pode definir o seu
NavController
:nav.scala.html
Então, na minha visão principal, posso chamar isso
NavController
:fonte
Eu apoio a resposta de Stian. Essa é uma maneira muito rápida de obter resultados.
Acabei de migrar do Java + Play1.0 para o Java + Play2.0 e os modelos são a parte mais difícil até agora, e a melhor maneira que encontrei para implementar um modelo base (para título, cabeçalho etc.) é usando o Http .Contexto.
Há uma sintaxe muito agradável que você pode obter com tags.
onde get.scala.html é:
e set.scala.html é:
significa que você pode escrever o seguinte em qualquer modelo
Portanto, é muito legível e agradável.
Foi assim que eu escolhi seguir. stian - bom conselho. Prova que é importante rolar para baixo para ver todas as respostas. :)
Passando variáveis HTML
Ainda não descobri como passar variáveis Html.
@ (título: String, conteúdo: Html)
no entanto, eu sei como passá-los como bloco.
@ (título: String) (conteúdo: Html)
portanto, convém substituir set.scala.html por
Dessa forma, você pode passar blocos Html dessa maneira
Edição: efeito colateral com minha implementação "Set"
Um caso de uso comum de herança de modelo no Play.
Você tem um base_template.html e, em seguida, tem page_template.html que estende base_template.html.
base_template.html pode parecer algo como
enquanto o modelo da página pode parecer algo como
e então você tem uma página (vamos assumir login_page.html) que se parece com
O importante a ser observado aqui é que você define "corpo" duas vezes. Uma vez em "login_page.html" e depois em "page_template.html".
Parece que isso desencadeia um efeito colateral, desde que você implemente set.scala.html como sugeri acima.
pois a página mostraria "coisas de login ..." duas vezes porque put retorna o valor que aparece na segunda vez em que colocamos a mesma chave. (consulte colocar assinatura nos documentos java).
O scala fornece uma maneira melhor de modificar o mapa
o que não causa esse efeito colateral.
fonte
args
contexto após a chamada atual.Se você estiver usando Java e quiser apenas a maneira mais simples possível, sem precisar escrever um interceptador e usar a anotação @With, também poderá acessar o contexto HTTP diretamente do modelo.
Por exemplo, se você precisar de uma variável disponível em um modelo, poderá adicioná-la ao contexto HTTP com:
Você pode acessá-lo no modelo com:
Obviamente, se você mesclar seus métodos com Http.Context.current (). Args.put ("", ""), é melhor usar um interceptador, mas em casos simples, isso pode ser suficiente.
fonte
Pela resposta de Stian, tentei uma abordagem diferente. Isso funciona para mim.
CÓDIGO JAVA
NA CABEÇA DE MODELO HTML
E USAR COMO
fonte