2013-04-18 42 views
33

Tôi đang làm việc theo cách của mình thông qua hướng dẫn AngularJS. Angular sử dụng cơ chế định tuyến JS của riêng nó để cho phép các ứng dụng trang đơn. Tệp định tuyến mẫu cho Angular trông giống như sau:Play Framework 2.1 - AngularJS định tuyến - giải pháp tốt nhất?

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'}); 
}]); 

Tôi đang cố gắng tìm ra một nơi tốt để lưu trữ partials của tôi (Tệp HTML cụ thể góc). Lý tưởng nhất là tôi muốn khả năng tạo mẫu chúng từ bên trong Play (tức là có chúng dưới dạng tệp * .scala.html). Tôi có thể thực hiện điều này bằng aa Chơi nộp các tuyến đường như vậy:

GET  /partials/phone_index  controllers.Application.phone_index 

tôi về cơ bản partials/đến một hành động điều khiển như thế này:

def phone_index = Action { 
    Ok(views.html.partials.phone_index()) 
} 

Giải pháp Tôi đang tìm kiếm là một sự kết hợp của hai ý tưởng:

  1. Tôi sẽ có một số loại ánh xạ cho phép tôi truy cập bất kỳ tệp nào trong/một phần/* và lấy lại tệp một phần.
  2. Tôi muốn ghi đè tuyến đường đến một phần cụ thể để tôi CAN sử dụng thao tác điều khiển để điền dữ liệu động (hiếm).

Bất kỳ ý tưởng nào?

Trả lời

32

Khi tôi đã cố gắng một cái gì đó tương tự như tôi đi đến kết luận rằng nó tốt hơn để phá vỡ nó vào 2 phần:

  • Sử dụng Chơi như một backend bạn tương tác với thông qua Ajax gọi
  • Store mẫu kiễu góc trong Chơi public thư mục (giống như /public/angular/) và sử dụng cách AngularJs mặc định để ánh xạ các mẫu

Tôi biết nó không âm thanh tuyệt vời và thực sự không trả lời câu hỏi của bạn về cách thực hiện, nhưng cố gắng liên kết cả hai khung có thể có vấn đề do cách mẫu và url của chúng được ánh xạ trong Góc và lợi ích sẽ rất nhỏ vì mọi thay đổi sẽ hàm ý rất nhiều công việc, do đó xóa lợi ích chính cho cả Play và Angular, phát triển nhanh chóng.

Điều này cũng cho phép bạn tách mối quan tâm tốt hơn, nếu dự án của bạn phát triển có thể quan trọng vì bạn chỉ có thể lấy mã AngularJS như một ứng dụng độc lập kết nối với một chương trình phụ trợ và nó sẽ hoạt động tốt.

Bạn có thể thấy một số mã mẫu về những gì tôi đã nói (dựa trên hướng dẫn TODO của AngularJS) trong số Github repository này. Tôi cảnh báo bạn, mã không phải là quá tốt đẹp, nhưng nên cung cấp cho bạn một ý tưởng và như một tiền thưởng cho bạn thấy làm thế nào để tích hợp Jasmine vào Play, cho thử nghiệm đơn vị AngularJS.

+2

Tôi nghĩ đây có lẽ là cách tiếp cận mà tôi cần phải thực hiện. –

+0

Vâng, cách tiếp cận này không hoạt động nếu thuộc tính "play.http.context" được đặt. Các tuyến đường sẽ bỏ lỡ tiền tố ngữ cảnh và do đó sẽ thất bại. Bất kỳ suy nghĩ nào để khắc phục vấn đề này? – user2715478

1

Đối với câu hỏi # 1 bạn có thể giới thiệu một con đường như thế này:

/partials/:view controllers.Application.showView(view:String) 

Sau đó, trong bộ điều khiển của bạn, bạn sẽ cần để ánh xạ từ tên xem để xem thực tế:

Map("phone_index" -> views.html.partials.phone_index()) 

Bạn có thể muốn làm cho các mẫu trở nên lười biếng hoặc yêu cầu có mặt, sau đó bạn có thể nên làm như sau:

val routes = Map(
    "phone_index" -> { implicit r:RequestHeader => 
    views.html.partials.phone_index()) 
    } 
.210

hành động của bạn sẽ giống như thế này:

def showView(view:String) = 
    Action { implicit r => 
    routes(view) 
    } 

Nếu bạn muốn có một phương pháp điều khiển cụ thể đối với một lộ trình nhất định (câu hỏi # 2), bạn đơn giản thêm một tuyến đường trên năng động một:

/partials/specific controllers.Application.specific() 
+0

này sẽ làm việc. Nhưng nó đòi hỏi phải sử dụng một bản đồ của các tên tuyến để điều khiển. Nó không phải là một số tiền lớn hơn. Cảm ơn bạn mặc dù. Hy vọng nó sẽ giúp người khác. –

1

Tôi thực sự nghĩ rằng đó không phải là một ý tưởng rất hay ngay cả khi nó đến từ một tâm trí thực sự trân trọng.

Tôi nghĩ rằng đó là một thực hành rất tốt để mọi suy nghĩ như mặc định (quy ước về nguyên tắc cấu hình) có nghĩa là chúng tôi có thể quan tâm nhiều hơn để giữ cho mỗi Paradigms (Play và AngularJS) được phân tách như một hoặc cả hai có thể phát triển trong tương lai gần hoặc xa sẽ có chi phí bảo trì mã.

Điểm quan trọng thứ hai là khả năng kiểm tra, nếu bạn kết hợp cả hai kỹ thuật, bạn sẽ kết thúc với một kết hợp để tìm ra các thử nghiệm tốt ở cả hai bên ứng dụng của bạn. Cheers

3

này sẽ không trả lời câu hỏi của bạn trực tiếp, nhưng tôi thấy điều này là cách tốt nhất để xây dựng Chơi + ứng dụng kiễu góc:

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

+1

Điều tôi không thích ở đây là sử dụng requireJS và webjars ngay từ đầu. Đối với tôi điều này có ý nghĩa để thêm sau. (nó không đơn giản như maven trong java như đối với tôi). Điều này hoạt động tốt khi ứng dụng đủ lớn. Và điều này không thay đổi những gì đã được nói bởi + Pere Villega về 'phát triển nhanh' – ses

3

Vâng, nó có thể tạo server-side meta -templates của các mẫu phía máy khách. Điều này cung cấp một số khả năng độc đáo, vì hai phương pháp không chồng chéo hoàn toàn. Ngoài ra còn có rất nhiều chỗ cho sự nhầm lẫn vì vậy hãy chắc chắn bạn biết lý do tại sao bạn đang viết một khối Play thay vì một chỉ thị góc.

Có hay không bạn nên làm điều đó vẫn là một câu hỏi mở; nó thực sự phụ thuộc vào việc bạn thực sự cần truy cập vào thông tin máy chủ trong các mẫu của bạn hay không. Một ví dụ về nơi tôi nghĩ rằng nó sẽ là cần thiết và thích hợp sẽ được thực hiện kiểm soát truy cập trong quan điểm của bạn.

Bây giờ để trả lời câu hỏi của bạn. Vấn đề được giải quyết bằng cách nội tuyến các partials thay vì cố gắng cung cấp một lộ trình cho chúng được tải theo yêu cầu. Xem http://docs.angularjs.org/api/ng.directive:script.

Đây là những gì mẫu trông giống như:

@(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> 

Và ứng dụng:

'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'}); 
}]); 

Chỉ cần bao gồm helper này:

@** 
* @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> 

Và hãy chắc chắn để sử dụng nó trong thư mục gốc phạm vi ứng dụng góc cạnh của bạn.

4

Hạt giống cuối cùng (https://github.com/angyjoe/eventual) là một cách khác để tạo ứng dụng Play + AngularJS. Mã này là một người yêu và được tài liệu hóa.

+2

Bạn có thể muốn tiết lộ ở đây, kiểm tra của tôi cho thấy bạn là tác giả của điều đó. Điều đó tự nó không phải là một tội phạm, nó dường như là thông tin liên quan, chỉ cần chúng tôi không vui lòng quảng cáo quá nhiều. –

+0

Thats tốt, như tôi đã nói, mọi người tin tưởng bạn nhiều hơn nếu bạn mở và nói điều gì đó như 'Tiết lộ: Tôi là tác giả của công cụ đã nói, và nó được viết để trả lời câu hỏi này'. –

1

này có thể không trả lời câu hỏi một cách chính xác nhưng bạn có thể thử làm theo dự án này vì nó dường như ví dụ điển hình để xây dựng Play/scala/apps góc:

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

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

+0

Đây là hướng dẫn cho mẫu này https://github.com/lashford/modern-web-template#master http://www.cakesolutions.net/teamblogs/2014/03/13/reactivemongo-play-angularjs –

Các vấn đề liên quan