В play1 я обычно получаю все данные в действиях, использую их непосредственно в представлениях. Поскольку нам не нужно явно объявлять параметры в поле зрения, это очень просто.
Но в play2 я обнаружил, что мы должны объявить все параметры (в том числе request
) в заголовке представлений, будет очень скучно получать все данные в действиях и передавать их в представления.
Например, если мне нужно отобразить меню, загруженные из базы данных, на главной странице, я должен определить его в 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>
Затем я должен объявить это на каждой подстранице:
@(menus: Seq[Menu])
@main("SubPage", menus) {
...
}
Затем мне нужно получить меню и передать его для просмотра при каждом действии:
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))
}
Пока это только один параметр main.scala.html
, а если их много?
Итак, наконец, я решил все Menu.findAll()
прямо в виду:
@(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>
Я не знаю, хорошо это или рекомендуется, есть ли лучшее решение для этого?
источник
Ответы:
На мой взгляд, тот факт, что шаблоны статически типизированы, на самом деле хорошо : вы гарантируете, что вызов вашего шаблона не завершится ошибкой, если он компилируется.
Однако он действительно добавляет некоторый шаблон на вызывающие сайты. Но вы можете уменьшить его (не теряя преимуществ статической печати).
В Scala я вижу два способа добиться этого: путем композиции действий или с помощью неявных параметров. В Java я предлагаю использовать
Http.Context.args
карту для хранения полезных значений и извлечения их из шаблонов без явной передачи в качестве параметров шаблонов.Использование неявных параметров
Поместите
menus
параметр в конецmain.scala.html
параметров вашего шаблона и отметьте его как «неявный»:Теперь, если у вас есть шаблоны, вызывающие этот основной шаблон, вы можете
menus
неявно передать параметр вmain
шаблон компилятором Scala, если он также объявлен как неявный параметр в этих шаблонах:Но если вы хотите, чтобы он неявно передавался из вашего контроллера, вам необходимо предоставить его как неявное значение, доступное в области, из которой вы вызываете шаблон. Например, вы можете объявить в своем контроллере следующий метод:
Тогда в своих действиях вы сможете просто написать следующее:
Вы можете найти дополнительную информацию об этом подходе в этом сообщении блога и в этом примере кода .
Обновление : здесь также был написан хороший пост в блоге, демонстрирующий этот шаблон .
Использование композиции действий
На самом деле, часто бывает полезно передать
RequestHeader
значение шаблонам (см., Например, этот образец ). Это не добавляет столько шаблонов в код вашего контроллера, потому что вы можете легко написать действия, получающие неявное значение запроса:Итак, поскольку шаблоны часто получают по крайней мере этот неявный параметр, вы можете заменить его более богатым значением, содержащим, например, ваши меню. Вы можете сделать это, используя механизм композиции действий Play 2.
Для этого вам нужно определить свой
Context
класс, обернув базовый запрос:Затем вы можете определить следующий
ActionWithMenu
метод:Что можно использовать так:
И вы можете использовать контекст как неявный параметр в своих шаблонах. Например, для
main.scala.html
:Использование композиции действий позволяет объединить все неявные значения, которые требуются вашим шаблонам, в одно значение, но, с другой стороны, вы можете потерять некоторую гибкость ...
Использование Http.Context (Java)
Поскольку в Java нет механизма неявных выражений Scala или аналогичного, если вы не хотите явно передавать параметры шаблонов, можно сохранить их в
Http.Context
объекте, который существует только на время запроса. Этот объект содержитargs
значение типаMap<String, Object>
.Таким образом, вы можете начать с написания перехватчика, как описано в документации :
Статический метод - это просто сокращение для извлечения меню из текущего контекста. Затем аннотируйте свой контроллер, который будет смешан с
Menus
перехватчиком действия:Наконец,
menus
получите значение из ваших шаблонов следующим образом:источник
@for(menu <- Menus.current()) {
ноMenus
никогда не определяете (вы помещаете меню (нижний регистр) :)ctx.args.put("menus", Menu.find.all());
. Есть причина? Например, Play, который переводит его в верхний регистр или что-то в этом роде?Menus
класс (перехватчик Java). @adis Да, но вы можете хранить их в другом месте, даже в кеше.То, как я это делаю, - просто создать новый контроллер для моей навигации / меню и вызвать его из представления
Итак, вы можете определить свои
NavController
:nav.scala.html
Тогда в моем основном представлении я могу назвать это
NavController
:источник
Поддерживаю ответ Стана. Это очень быстрый способ получить результат.
Я только что перешел с Java + Play1.0 на Java + Play2.0, и шаблоны являются самой сложной частью, и лучший способ, который я нашел для реализации базового шаблона (для заголовка, заголовка и т. Д.), - использовать Http .Context.
Есть очень хороший синтаксис, которого можно добиться с помощью тегов.
где get.scala.html - это:
а set.scala.html:
означает, что вы можете написать следующее в любом шаблоне
Так что это очень читабельно и приятно.
Я выбрал именно этот путь. стиан - хороший совет. Доказывает важность прокрутки вниз, чтобы увидеть все ответы. :)
Передача переменных HTML
Я еще не понял, как передавать переменные Html.
@ (Название: String, содержание: Html)
однако я знаю, как передать их как блок.
@ (Название: String) (содержание: Html)
поэтому вы можете заменить set.scala.html на
таким образом вы можете передавать блоки Html вот так
РЕДАКТИРОВАТЬ: побочный эффект с моей реализацией "Set"
Распространенный вариант использования - это наследование шаблонов в Play.
У вас есть base_template.html, а затем у вас есть page_template.html, расширяющий base_template.html.
base_template.html может выглядеть примерно так
в то время как шаблон страницы может выглядеть примерно так
а затем у вас есть страница (допустим, login_page.html), которая выглядит как
Здесь важно отметить, что вы устанавливаете "body" дважды. Один раз в "login_page.html", а затем в "page_template.html".
Похоже, что это вызывает побочный эффект, если вы реализуете set.scala.html, как я предлагал выше.
поскольку на странице дважды будет отображаться «материал для входа ...», потому что команда put возвращает значение, которое появляется во второй раз, когда мы вводим тот же ключ. (см. подпись в java-документах).
scala предоставляет лучший способ изменить карту
который не вызывает этого побочного эффекта.
источник
args
контекст после вызова текущим.Если вы используете Java и просто хотите получить самый простой способ без написания перехватчика и использования аннотации @With, вы также можете получить доступ к контексту HTTP прямо из шаблона.
Например, если вам нужна переменная, доступная из шаблона, вы можете добавить ее в контекст HTTP с помощью:
Затем вы можете получить к нему доступ из шаблона с помощью:
Очевидно, что если вы засоряете свои методы Http.Context.current (). Args.put ("", ""), вам лучше использовать перехватчик, но в простых случаях он может помочь.
источник
Судя по ответу Стиана, я попробовал другой подход. У меня это работает.
В КОДЕ JAVA
В ЗАГОЛОВКЕ ШАБЛОНА HTML
И ИСПОЛЬЗУЙТЕ КАК
источник