简体   繁体   English

Ajax通过javascript路由,控制器应返回json并返回html页面

[英]Ajax through javascript route, controller should return json and return html page

Environment : scala 2.10, play 2.1.1, eclipse 4.2 环境:scala 2.10,play 2.1.1,eclipse 4.2

Use case : the user click on a link figuring an object (game) in the database. 用例:用户单击确定数据库中对象(游戏)的链接。 An ajax request is sent through Javascript Route to a controller, which load the game data, convert it to json and send it back to view. Ajax请求通过Javascript Route发送到控制器,该控制器加载游戏数据,将其转换为json并发送回视图。 The ajax success callback print the game title into a div. Ajax成功回调将游戏标题打印到div中。

Problem: i dont get a json, but the a html page (the page from which the ajax request s sent). 问题:我没有得到json,但是有一个html页面(从其发送ajax请求的页面)。

I suspect the problem is in the router : i put a print("route") in the javascript route action and a print("load game") in load game action. 我怀疑问题出在路由器:我在javascript路线操作中放置了print(“ route”),在载入游戏操作中放置了print(“ load game”)。 The "route" is displayed in console, but not the "load game". “路线”显示在控制台中,但不显示“加载游戏”。 It may also come from my loadGame(id) route, but i dont see how i should set it. 它也可能来自我的loadGame(id)路线,但我不知道如何设置它。

Here is my code. 这是我的代码。

Routes: 路线:

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
GET     /                               controllers.Application.index

# Javascript routes
GET     /javascriptRoutes               controllers.Application.javascriptRoutes

# Library
GET     /library/:id                    controllers.UserController.library(id: Long)
GET     /library/:id                    controllers.GameController.loadGame(id: Long)

View: 视图:

<div class="span2">
                    <ul class="nav nav-pills nav-stacked">
                        @userGames.map { game =>
                            <li><a href="#" onclick="displayGameInfo(@game.id)">@game.title</a></li>
                        }
                    </ul>
                </div>
...
<script>
            var successFn = function(data) {
                $('#gameInfo').html('');
                $("#gameInfo").append('<h4>'+data.title+'</h4>')
            }

            var errorFn = function(err) {
                console.debug("Error of ajax Call");
                console.debug(err);
            }

            ajax1 = {
                dataType: 'text',
                contentType:'application/json',
                success: successFn,
                error: errorFn
            }

            var displayGameInfo = function(id) {
                javascriptRoutes.controllers.GameController.loadGame(id)
                    .ajax(ajax1);
            }
        </script>

ApplicationController with javascript route: ... 具有JavaScript路线的ApplicationController:...

object Application extends Controller {
  def javascriptRoutes = Action { implicit request =>
    import routes.javascript._
        println("-=== route ===-")
        Ok(
            Routes.javascriptRouter("javascriptRoutes")(routes.javascript.GameController.loadGame)
        ).as("text/javascript")
  }
}

GameController with loadGame(id) method: 带有loadGame(id)方法的GameController:

object GameController extends Controller {
...
  // Library
  def loadGame(id: Long) = Action(parse.json) { implicit request =>
    println("-=== load game ===-")
    val mess = Json.toJson(Game.find(id))
    Ok(mess)
  }

}

Game model: 游戏模型:

case class Game(id: Long, title: String, description: String, userId: Long)

object Game {

  val game = {
    get[Long]("id") ~ 
    get[String]("title") ~
    get[String]("description") ~
    get[Long]("userId") map {
        case id~title~description~userId => Game(id, title, description, userId)
    }
  }

...

  def find(id: Long): Game = DB.withConnection { implicit c =>
    SQL("select * from game where id = {id}")
        .on('id -> id).as(game *).head
  }


  implicit object GameFormat extends Format[Game] {

    def reads(json: JsValue) = JsSuccess(Game(   
      (json \ "id").as[Long],
      (json \ "title").as[String],
      (json \ "description").as[String],
      (json \ "uid").as[Long]
    ))

    def writes(game: Game) = JsObject(Seq(
      "id" -> JsNumber(game.id),
      "title" -> JsString(game.title),
      "description" -> JsString(game.description),
      "userId" -> JsNumber(game.userId))
      )
  }
}

In your routes file, you have to routes matching the same URL : routes文件中,您必须匹配相同URL的路由:

# Library
GET     /library/:id                    controllers.UserController.library(id: Long)
GET     /library/:id                    controllers.GameController.loadGame(id: Long)

When your browser request the /library/123 url, Play will try the routes in the order of declaration and will match the first one, calling the controllers.UserController.library() Action. 当您的浏览器请求/library/123网址时,Play会按照声明的顺序尝试路由,并匹配第一个路由,并调用controllers.UserController.library()操作。 This is probably why you get a full HMTL page. 这可能就是为什么获得完整的HMTL页面的原因。

Try to define a different URL for the second route (the one returning JSON) and Play will be able to match the correct Action. 尝试为第二条路线(返回JSON的那个)定义一个不同的URL,然后Play就能匹配正确的Action。

Ex : 例如:

GET     /library/:id                    controllers.UserController.library(id: Long)
GET     /gameData/:id                   controllers.GameController.loadGame(id: Long)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM