Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Play Framework 2.1-AngularJS路由-最佳解决方案?_Scala_Angularjs_Playframework - Fatal编程技术网

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

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

我正在学习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'});
}]);
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)
  }
我正在寻找的解决方案是两种理想的结合:

  • 我会有某种映射,让我可以访问/partial/*下的任何文件,并获取部分文件
  • 我希望覆盖到特定部分的路由,以便我可以使用控制器操作动态填充数据(很少)
  • 有什么想法吗

    对于问题1,您可以引入如下路线:

    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
      文件夹中(类似于
      /public/Angular/
      ),并使用默认的AngularJs方式映射模板
    我知道这听起来不太好,也没有回答你关于如何做的问题,但是尝试链接这两个框架可能会有问题,因为模板和它们的URL是以Angular方式映射的,而且好处很小,因为任何更改都会意味着大量工作,从而消除了Play和Angular的主要好处,快速发展

    这还允许您更好地分离关注点,如果您的项目增长,这可能很重要,因为您可以将AngularJS代码作为一个独立的应用程序连接到后端,它将正常工作


    您可以在本文中看到我所说的一些示例代码(基于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关于“快速发展”的说法。你可能想在这里披露,我的检查表明你是这篇文章的作者。这本身并不是犯罪,它似乎是相关的信息,只是我们不喜欢做太多的广告。这很好,正如我所说,如果你是开放的,并且说一些类似于
    披露的话,人们会更信任你:我是上述工具的作者,它是针对这个问题编写的