Scala Play Framework 2.1-AngularJS路由-最佳解决方案?
我正在学习AngularJS教程。Angular使用自己的JS路由机制来支持单页应用程序。Angular的示例路由文件如下所示:Scala Play Framework 2.1-AngularJS路由-最佳解决方案?,scala,angularjs,playframework,Scala,Angularjs,Playframework,我正在学习AngularJS教程。Angular使用自己的JS路由机制来支持单页应用程序。Angular的示例路由文件如下所示: angular.module('phonecat', []). config(['$routeProvider', function($routeProvider) { $routeProvider. when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneL
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
/partials/:view controllers.Application.showView(view:String)
val routes = Map(
"phone_index" -> { implicit r:RequestHeader =>
views.html.partials.phone_index())
}
def showView(view:String) =
Action { implicit r =>
routes(view)
}
我试图找到一个好地方来存储我的片段(角度特定的HTML文件)。理想情况下,我希望能够从游戏中对它们进行模板化(即将它们作为*.scala.html文件)。我可以使用播放路线文件完成此操作,如下所示:
GET /partials/phone_index controllers.Application.phone_index
我基本上是这样的控制器动作的一部分:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
/partials/:view controllers.Application.showView(view:String)
val routes = Map(
"phone_index" -> { implicit r:RequestHeader =>
views.html.partials.phone_index())
}
def showView(view:String) =
Action { implicit r =>
routes(view)
}
我正在寻找的解决方案是两种理想的结合:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
/partials/:view controllers.Application.showView(view:String)
val routes = Map(
"phone_index" -> { implicit r:RequestHeader =>
views.html.partials.phone_index())
}
def showView(view:String) =
Action { implicit r =>
routes(view)
}
然后在控制器中,您需要从视图名称映射到实际视图:
Map("phone_index" -> views.html.partials.phone_index())
您可能希望使模板延迟或要求请求存在,然后您可能应该执行以下操作:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
/partials/:view controllers.Application.showView(view:String)
val routes = Map(
"phone_index" -> { implicit r:RequestHeader =>
views.html.partials.phone_index())
}
def showView(view:String) =
Action { implicit r =>
routes(view)
}
您的操作如下所示:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: '/partials/phone-list', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
/partials/:view controllers.Application.showView(view:String)
val routes = Map(
"phone_index" -> { implicit r:RequestHeader =>
views.html.partials.phone_index())
}
def showView(view:String) =
Action { implicit r =>
routes(view)
}
如果您想为某条路线(问题#2)使用特定的控制器方法,只需在动态路线上方添加一条路线:
/partials/specific controllers.Application.specific()
当我尝试类似的东西时,我得出结论,最好将其分为两部分:
- 使用Play作为通过Ajax调用进行交互的后端
- 将角度模板存储在Play
文件夹中(类似于public
),并使用默认的AngularJs方式映射模板/public/Angular/
您可以在本文中看到我所说的一些示例代码(基于AngularJS的TODO教程)。我警告你,代码不是很好,但应该会给你一个想法,作为奖励,你会看到如何将Jasmine集成到AngularJS单元测试中。我真的认为这不是一个很好的主意,即使它确实来自一个尊重的想法 我认为将每个想法都保留为默认(约定优先于配置原则)是一种非常好的做法,这意味着对我来说,我们可能更感兴趣的是将每个范例(Play和AngularJS)分开,因为一个或两个范例可能会在近期或远期演变,这将导致代码维护的成本 第二个非常重要的一点是可测试性,如果您混合使用这两种技术,那么最终您将得到一种混合,从而在应用程序的两侧都能提供真正良好的测试覆盖率。
干杯这不会直接回答您的问题,但我发现这是构建Play+Angular应用程序的最佳方式:
是的,可以创建客户端模板的服务器端元模板。这提供了一些独特的功能,因为这两种方法并不完全重叠。还有很大的混淆空间,所以请确保您知道为什么要编写播放块而不是角度指令 你是否应该这样做仍然是一个悬而未决的问题;这实际上取决于您是否确实需要访问模板中的服务器信息。我认为在您的视图中实现访问控制是必要和适当的 现在回答你的问题。这个问题是通过内联partials来解决的,而不是试图为它们提供一条按需加载的路径。看 以下是模板的外观:
@(id: Long)(implicit request: RequestWithUser[AnyContent])
@import helper._
<!doctype html>
<html lang="en" ng-app="phonecat">
<head>
<meta charset="utf-8">
<title>Google Phone Gallery</title>
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/bootstrap.css">
<script src="lib/angular/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/services.js"></script>
<script src="lib/angular/angular-resource.js"></script>
</head>
<body>
<div ng-view></div>
@ngTemplate("phone-list.html") {
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">Hello @request.user.name</div>
</div>
<div class="row-fluid">
<div class="span2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
<option value="name">Alphabetical</option>
<option value="age">Newest</option>
</select>
</div>
<div class="span10">
<!--Body content-->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</div>
</div>
}
@ngTemplate("phone-detail.html") {
<img ng-src="{{mainImageUrl}}" class="phone">
<h1>{{phone.name}}</h1>
<p>{{phone.description}}</p>
<ul class="phone-thumbs">
<li ng-repeat="img in phone.images">
<img ng-src="{{img}}" ng-click="setImage(img)">
</li>
</ul>
<ul class="specs">
<li>
<span>Availability and Networks</span>
<dl>
<dt>Availability</dt>
<dd ng-repeat="availability in phone.availability">{{availability}}</dd>
</dl>
</li>
</ul>
}
</body>
</html>
只需包含此帮助程序:
@**
* @ngTemplate
* Generate an AngularJS inlined template.
*
* Note: Do not include scripts in your @template HTML. This will break the template.
*
* @param name
* @param template
*@
@(name: String)(template: Html)
<script type="text/ng-template" id="@name">@template</script>
@**
*@ngTemplate
*生成AngularJS内联模板。
*
*注意:不要在@template HTML中包含脚本。这将破坏模板。
*
*@param name
*@param模板
*@
@(名称:字符串)(模板:Html)
@模板
并确保在angular应用程序的根范围内使用它。最终种子()是构建Play+AngularJS应用程序的另一种方法。这段代码是一段很好的文档。这可能无法准确回答问题,但您可以尝试遵循此项目,因为它似乎是构建Play/scala/Angular应用程序的好例子:
这会有用的。但它需要使用到控制器的路由名称映射。这不是一个很大的数字更好。谢谢你。希望它能帮助其他人。我认为这可能是我需要采用的方法。如果设置了“play.http.context”属性,这种方法就不起作用。路由将丢失上下文前缀,因此将失败。有什么想法可以克服这个问题吗?我不喜欢在开始时使用requireJS和Webjar。对我来说,这是有意义的添加后。(对我来说,它不像java中的maven那么简单)。当应用程序足够大时,这种方法效果很好。这并没有改变Pere Villega关于“快速发展”的说法。你可能想在这里披露,我的检查表明你是这篇文章的作者。这本身并不是犯罪,它似乎是相关的信息,只是我们不喜欢做太多的广告。这很好,正如我所说,如果你是开放的,并且说一些类似于
披露的话,人们会更信任你:我是上述工具的作者,它是针对这个问题编写的