[英]Play Framework 2.1 - AngularJS routing - best solution?
我正在通過AngularJS教程。 Angular使用它自己的JS路由機制來允許單頁應用程序。 Angular的示例路由文件如下所示:
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'});
}]);
我試圖找到一個存儲我的部分(Angular特定HTML文件)的好地方。 理想情況下,我喜歡在Play中模擬它們的能力(即將它們作為* .scala.html文件)。 我可以使用如下的播放路徑文件來完成此操作:
GET /partials/phone_index controllers.Application.phone_index
我基本上偏愛/像這樣的控制器動作:
def phone_index = Action {
Ok(views.html.partials.phone_index())
}
我正在尋找的解決方案是兩個理想的組合:
有任何想法嗎?
當我嘗試類似的東西時,我得出的結論是,最好將其分為兩部分:
public
文件夾(類似/public/angular/
)中,並使用默認的AngularJs方式映射模板 我知道這聽起來不太好,並且真的沒有回答你關於如何做到這一點的問題,但是由於模板和它們的URL在Angular中的映射方式,嘗試鏈接兩個框架可能會有問題,並且它的好處將非常大因為任何改變都意味着很多工作,因此消除了Play和Angular的快速發展的主要好處。
這也允許您更好地分離關注點,如果您的項目增長可能很重要,因為您可以將AngularJS代碼作為連接到后端的獨立應用程序取消,它將正常工作。
您可以在此Github存儲庫中看到我所說的示例代碼(基於AngularJS的TODO教程)。 我警告你,代碼不太好,但應該給你一個想法,作為獎勵向你展示如何將Jasmine整合到Play中,用於AngularJS單元測試。
最終種子( https://github.com/angyjoe/eventual )是另一種構建Play + AngularJS應用程序的方法。 代碼是一個甜心並且有詳細記錄。
這不會直接回答你的問題,但我發現這是構建Play + Angular應用程序的最佳方式:
是的,可以創建客戶端模板的服務器端元模板。 這提供了一些獨特的能力,因為這兩種方法並不完全重疊。 還有很多混淆的空間,所以一定要知道為什么要編寫Play塊而不是Angular指令。
你是否應該這樣做仍然是一個懸而未決的問題; 這實際上取決於您是否確實需要訪問模板中的服務器信息。 我認為必要且適當的一個例子是在視圖中實現訪問控制。
現在回答你的問題。 通過內聯部分而不是試圖提供按需加載它們的路由來解決該問題。 見http://docs.angularjs.org/api/ng.directive:script 。
這是模板的樣子:
@(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>
和應用程序:
'use strict';
/* App Module */
angular.module('phonecat', ['phonecatFilters', 'phonecatServices']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
只需包括這個幫手:
@**
* @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>
並確保在角度應用程序的根范圍內使用它。
對於問題#1,您可以引入這樣的路線:
/partials/:view controllers.Application.showView(view:String)
然后在您的控制器中,您需要從視圖名稱映射到實際視圖:
Map("phone_index" -> views.html.partials.phone_index())
您可能希望將模板呈現為惰性或要求存在請求,那么您應該執行以下操作:
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和AngularJS)分開,因為其中一個或兩個可以在近處或遙遠的未來將有代碼維護的成本。
第二個非常重要的一點是可測試性,如果你混合兩種技術,你最終會得到一個混合,以便在應用程序的兩側提供真正良好的測試覆蓋率。 干杯
這可能不會完全回答這個問題,但你可以嘗試按照這個項目,因為它似乎是構建Play / scala / Angular應用程序的好例子:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.