В моем шаблоне основного вида я хочу отображать динамические данные (из базы данных), например элементы навигации для веб-сайта.Как передать модель в мой основной шаблон просмотра без дублирования кода в каждом контроллере?
Когда я добавляю модель к шаблону в качестве параметра, для представления модели для основного шаблона требуется каждое представление, использующее мой основной шаблон. Следовательно, каждое действие в каждом контроллере сначала должно получить модель навигации для основного шаблона.
Этот подход приведет к дублированию кода и нарушению принципа единой ответственности, поскольку каждое действие должно знать, как получить основную модель шаблона. Есть ли способ обеспечить описанную функциональность без дублирования кода изолированным образом, сохраняя при этом код проверяемым?
Пример
Ниже может быть использован для имитации модели, и сервисные классы:
package services
import scala.concurrent.Future
case class HeaderItem(title: String, url: String)
case class User(name: String, email: String)
class HeaderItemService {
val all: Future[Seq[HeaderItem]] = Future.successful(HeaderItem("Home", "/") :: Nil)
}
class UserService {
val all: Future[Seq[User]] = Future.successful(User("Test", "[email protected]") :: Nil)
}
Основной шаблон представления отображает элементы заголовка:
@import services.HeaderItem
@(headerItems: Seq[HeaderItem])(content: Html)
<!DOCTYPE html>
<html lang="en">
<body>
<div id="header">
<ul>
@for(item <- headerItems) {
<li>@item.title</li>
}
</ul>
</div>
@content
</body>
</html>
Ребенок Вид на дисплей просматривает конкретные данные (пользователей) и должен передавать основные шаблоны шаблона:
@import services.HeaderItem
@import services.User
@(headerItems: Seq[HeaderItem], users: Seq[User])
@main(headerItems) {
<ul>
@for(user <- users) {
<li>@user.name</li>
}
</ul>
}
И это контроллер, который должен заботиться о том, а пункты навигации, а также пользователей:
package controllers
import javax.inject._
import play.api.mvc._
import services.{HeaderItemService, UserService}
import scala.concurrent.ExecutionContext.Implicits.global
@Singleton
class HomeController @Inject()(headerItemService: HeaderItemService, userService: UserService) extends Controller {
def index = Action.async {
for {
headerItems <- headerItemService.all
users <- userService.all
} yield Ok(views.html.index(headerItems, users))
}
}
Первые попытки
В ASP MVC проблема может подходить по оказанию действия внутри представления с использованием метода Html.RenderAction (https://msdn.microsoft.com/en-us/library/ee839451(v=vs.100).aspx). Насколько мне известно, подобный подход невозможен в рамках игры (2.4).
Вы можете использовать javascript в главном шаблоне, который будет извлекать элементы заголовка из отдельной конечной точки. –
@Lukasz: с помощью javascript я мог бы построить решение, аналогичное подходу ASP RenderAction, но также он ввел бы новые зависимости и сделал бы представления менее читаемым. Я бы предпочел решение, основанное только на Scala. – Felix