En play1, generalmente obtengo todos los datos en acciones, los uso directamente en las vistas. Como no necesitamos declarar explícitamente los parámetros a la vista, esto es muy fácil.
Pero en play2, descubrí que tenemos que declarar todos los parámetros (incluidos request
) en el encabezado de las vistas, será muy aburrido obtener todos los datos en acciones y pasarlos a las vistas.
Por ejemplo, si necesito mostrar menús cargados desde la base de datos en la página principal, tengo que definirlo en 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>
Luego tengo que declararlo en cada subpágina:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Luego tengo que obtener los menús y pasarlos para verlos en cada acción:
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 ahora es solo un parámetro main.scala.html
, ¿y si hay muchos?
Entonces, por fin, decidí a todos Menu.findAll()
directamente a la 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>
No sé si es bueno o recomendado, ¿hay alguna solución mejor para esto?
fuente
Respuestas:
En mi opinión, el hecho de que las plantillas estén estáticamente escritas es realmente bueno : tiene la garantía de que llamar a su plantilla no fallará si se compila.
Sin embargo, de hecho agrega algo repetitivo en los sitios de llamadas. Pero puede reducirlo (sin perder las ventajas de la escritura estática).
En Scala, veo dos formas de lograrlo: a través de la composición de acciones o mediante el uso de parámetros implícitos. En Java sugiero usar el
Http.Context.args
mapa para almacenar valores útiles y recuperarlos de las plantillas sin tener que pasarlos explícitamente como parámetros de plantillas.Usando parámetros implícitos
Coloque el
menus
parámetro al final de losmain.scala.html
parámetros de su plantilla y márquelo como "implícito":Ahora, si tiene plantillas que llaman a esta plantilla principal, puede hacer que el compilador Scala
menus
pase el parámetro implícitamente a lamain
plantilla si también se declara como un parámetro implícito en estas plantillas:Pero si desea que se pase implícitamente desde su controlador, debe proporcionarlo como un valor implícito, disponible en el ámbito desde donde llama a la plantilla. Por ejemplo, puede declarar el siguiente método en su controlador:
Luego, en sus acciones, podrá escribir lo siguiente:
Puede encontrar más información sobre este enfoque en esta publicación de blog y en este ejemplo de código .
Actualización : Aquí también se ha escrito una buena publicación de blog que demuestra este patrón .
Usar composición de acciones
En realidad, a menudo es útil pasar el
RequestHeader
valor a las plantillas (ver, por ejemplo, esta muestra ). Esto no agrega tanto repetitivo a su código de controlador porque puede escribir fácilmente acciones que reciben un valor de solicitud implícito:Entonces, dado que las plantillas a menudo reciben al menos este parámetro implícito, puede reemplazarlo con un valor más rico que contenga, por ejemplo, sus menús. Puedes hacerlo utilizando el mecanismo de composición de acciones de Play 2.
Para hacerlo, debe definir su
Context
clase, ajustando una solicitud subyacente:Luego puede definir el siguiente
ActionWithMenu
método:Que se puede usar así:
Y puede tomar el contexto como un parámetro implícito en sus plantillas. Por ejemplo para
main.scala.html
:El uso de la composición de acciones le permite agregar todos los valores implícitos que requieren sus plantillas en un solo valor, pero por otro lado puede perder algo de flexibilidad ...
Usando Http.Context (Java)
Dado que Java no tiene el mecanismo de implicaciones de Scala o similar, si desea evitar pasar parámetros de plantillas explícitamente, una posible forma es almacenarlos en el
Http.Context
objeto que vive solo durante la duración de una solicitud. Este objeto contiene unargs
valor de tipoMap<String, Object>
.Por lo tanto, puede comenzar escribiendo un interceptor, como se explica en la documentación :
El método estático es solo una abreviatura para recuperar los menús del contexto actual. Luego anote su controlador para mezclarlo con el
Menus
interceptor de acción:Finalmente, recupere el
menus
valor de sus plantillas de la siguiente manera:fuente
@for(menu <- Menus.current()) {
peroMenus
nunca está definido (coloca menús (minúsculas):)ctx.args.put("menus", Menu.find.all());
. ¿Hay una razón? ¿Te gusta jugar que lo transforma en mayúsculas o algo así?Menus
clase definida (el interceptor Java). @adis Sí, pero puedes guardarlos en otro lugar, incluso en el caché.La forma en que lo hago es crear un nuevo controlador para mi navegación / menú y llamarlo desde la vista
Para que pueda definir su
NavController
:nav.scala.html
Entonces, en mi vista principal, puedo llamar a eso
NavController
:fuente
Apoyo la respuesta de stian. Esta es una forma muy rápida de obtener resultados.
Acabo de migrar de Java + Play1.0 a Java + Play2.0 y las plantillas son la parte más difícil hasta ahora, y la mejor manera que encontré para implementar una plantilla base (por título, encabezado, etc.) es usando el Http .Contexto.
Hay una sintaxis muy buena que puedes lograr con las etiquetas.
donde get.scala.html es:
y set.scala.html es:
significa que puede escribir lo siguiente en cualquier plantilla
Por lo tanto, es muy legible y agradable.
Esta es la forma en que elegí ir. stian - buenos consejos. Demuestra que es importante desplazarse hacia abajo para ver todas las respuestas. :)
Pasando variables HTML
Todavía no he descubierto cómo pasar variables HTML.
@ (título: cadena, contenido: HTML)
Sin embargo, sé cómo pasarlos como bloque.
@ (título: Cadena) (contenido: HTML)
por lo que es posible que desee reemplazar set.scala.html con
de esta manera puedes pasar bloques Html así
EDITAR: efecto secundario con mi implementación "Set"
Un caso de uso común es la herencia de plantillas en Play.
Tiene una base_template.html y luego tiene page_template.html que extiende base_template.html.
base_template.html podría verse algo así
mientras que la plantilla de la página podría verse algo así
y luego tienes una página (supongamos que login_page.html) se parece a
Lo importante a tener en cuenta aquí es que configura "cuerpo" dos veces. Una vez en "login_page.html" y luego en "page_template.html".
Parece que esto desencadena un efecto secundario, siempre y cuando implemente set.scala.html como sugerí anteriormente.
ya que la página mostraría "cosas de inicio de sesión ..." dos veces porque put devuelve el valor que aparece la segunda vez que ponemos la misma clave. (ver poner firma en java docs).
Scala proporciona una mejor manera de modificar el mapa
que no causa este efecto secundario.
fuente
args
contexto posterior a la llamada actual.Si está utilizando Java y solo quiere la forma más simple posible sin tener que escribir un interceptor y utilizando la anotación @With, también puede acceder al contexto HTTP directamente desde la plantilla.
Por ejemplo, si necesita una variable disponible de una plantilla, puede agregarla al contexto HTTP con:
Luego puede acceder desde la plantilla con:
Obviamente, si ensucia sus métodos con Http.Context.current (). Args.put ("", "") es mejor que use un interceptor, pero para casos simples puede ser útil.
fuente
Por la respuesta de Stian, probé un enfoque diferente. Esto funciona para mi.
EN EL CÓDIGO JAVA
EN CABEZAL DE PLANTILLA HTML
Y UTILIZAR COMO
fuente