簡體   English   中英

Play Framework 2.1 - AngularJS路由 - 最佳解決方案?

[英]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())
}

我正在尋找的解決方案是兩個理想的組合:

  1. 我會有一些映射,讓我訪問/ partial / *下的任何文件,並獲取部分文件。
  2. 我想的路線的重寫到一個特定的部分,所以我可以使用一個控制器的動作與數據(罕見)動態地繼續進行。

有任何想法嗎?

當我嘗試類似的東西時,我得出的結論是,最好將其分為兩部分:

  • 使用Play作為通過Ajax調用進行交互的后端
  • 將Angular模板存儲在Play public文件夾(類似/public/angular/ )中,並使用默認的AngularJs方式映射模板

我知道這聽起來不太好,並且真的沒有回答你關於如何做到這一點的問題,但是由於模板和它們的URL在Angular中的映射方式,嘗試鏈接兩個框架可能會有問題,並且它的好處將非常大因為任何改變都意味着很多工作,因此消除了Play和Angular的快速發展的主要好處。

這也允許您更好地分離關注點,如果您的項目增長可能很重要,因為您可以將AngularJS代碼作為連接到后端的獨立應用程序取消,它將正常工作。

您可以在此Github存儲庫中看到我所說的示例代碼(基於AngularJS的TODO教程)。 我警告你,代碼不太好,但應該給你一個想法,作為獎勵向你展示如何將Jasmine整合到Play中,用於AngularJS單元測試。

最終種子( https://github.com/angyjoe/eventual )是另一種構建Play + AngularJS應用程序的方法。 代碼是一個甜心並且有詳細記錄。

這不會直接回答你的問題,但我發現這是構建Play + Angular應用程序的最佳方式:

https://github.com/typesafehub/angular-seed-play

是的,可以創建客戶端模板的服務器端元模板。 這提供了一些獨特的能力,因為這兩種方法並不完全重疊。 還有很多混淆的空間,所以一定要知道為什么要編寫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應用程序的好例子:

https://github.com/lashford/modern-web-template#master

http://typesafe.com/activator/template/modern-web-template

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM