Yes, it's possible to create server-side meta-templates of client-side templates. This offers some unique abilities, as the two methods don't overlap completely. There's also plenty of room for confusion so be sure you know why you're writing a Play block instead of an Angular directive.
Whether or not you should do it remains an open question; it really depends on whether you actually need access to server information in your templates. An example of where I think it would be necessary and appropriate would be for implementing access control in your views.
Now to answer your question. The problem is solved by inlining the partials instead of trying to provide a route for them to be loaded on demand. See http://docs.angularjs.org/api/ng.directive:script.
Here's what the template looks like:
@(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>
And the app:
'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'});
}]);
Just include this helper:
@**
* @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>
And make sure to use it within the root scope of your angular app.