Play 2.x:如何使用通用按钮发出 AJAX 请求

IT技术 javascript java ajax routes playframework-2.0
2021-02-12 05:02:09

所以我之前已经成功地让 AJAX 请求工作,但我总是不得不使用一个表单,然后在提交结束时返回 false 以便它不会刷新页面。

我最近也刚刚将我的 JavaScript 移动到一个单独的文件中,这导致我的 @ 命令失败。因此,我不知道如何将我的 URL 设置为我的路线?

HTML:

<button id="saveAsDefaultButton">Save as default</button>

Playframework Java 代码:

public static Result saveDefaultPhoneForUser(String handset) {
    User currentUser = User.findByName(session("name"));
    currentUser.lastControlledHandset = theHandset;
    currentUser.save();
    return ok();
}

路线:

POST    /                           controllers.Application.saveDefaultPhoneForUser(handset : String)

javascript:

$('#saveAsDefaultButton').click(function(evt) {
        $('#errors').hide();
        $.ajax({
            type : 'POST',
            url : "controllers.Application.saveDefaultPhoneForUser",
            data : $('#controlledPhone option:selected').text(),
            dataType : "text",
            success : function(data) {
                //setError('Call succedded');
                //$('#test1').attr("src", data)
            },
            error : function(data) {
                setError('Make call failed');
            }
        });
        return false;
    });

我确信有一种方法可以做到这一点,但我只是没有找到任何东西。

5个回答

对于这项工作,您应该使用javascriptRoutes因为它会根据您的 routes.conf 生成正确的 JS 路径。您将在 Zentask示例中找到使用示例

无论如何,现在您可以通过更改为url修复您的 AJAX 调用

url : '@routes.Application.saveDefaultPhoneForUser()',

这种方式要求它把整个JS放在模板中,这是错误的。它可以甚至应该移动到单独的 JS 文件中,并让您需要使用 javascriptRoutes。

更多的...

官方文档还没有javascriptRoutes进行描述,但是这里有一步一步的介绍。虽然描述看起来很复杂,但实际上使用这种方式会带来很多好处。

1. 创建公共路由

首先,您需要在conf/routes文件中创建公共路由

GET     /item/:id     controllers.Application.getItem(id: Long)
POST    /item/new     controllers.Application.newItem
PUT     /item/:id     controllers.Application.updateItem(id: Long)

当然,你至少需要在Application控制器中创建这三个动作

  • getItem(Long id){ ... }
  • newItem() { ... }
  • updateItem(Long id) { ... }

2. 创建一个动作,将常用路由翻译成 JS

  • 把它放在某个地方,即。在你的Application控制器中
  • 让我们称之为 javascriptRoutes()

在该操作中,您将指向文件中现有路由conf/routes

public static Result javascriptRoutes() {
    response().setContentType("text/javascript");
    return ok(
        Routes.javascriptRouter("myJsRoutes",
            routes.javascript.Application.getItem(),
            routes.javascript.Application.newItem(),
            routes.javascript.Application.updateItem(),
            //inside somepackage
            controllers.somepackage.routes.javascript.Application.updateItem()
        )
    );
}

注意:不要在括号中设置任何参数。

3. 创建javascriptRoutes行动路线并将其包含在您的模板中

路线 conf/routes

GET     /javascriptRoutes     controllers.Application.javascriptRoutes

查看<head>部分/views/main.scala.html

<script type="text/javascript" src='@routes.Application.javascriptRoutes()'></script>

4. 在你想要的地方使用 javascriptRoutes

从现在开始,您可以在 JS 中使用路由来获取正确的路径,而无需指定urltype举个例子,而不是:

 $('.getAjaxForThisContainer').click(function(e) {
    var idToGet = $("#someField").val();
    $.ajax({
        type : 'GET',
        url : '@routes.Application.getItem()',
        data : {
            id: idToGet
        },
        success : function(data) {
            // ... some code on success
        }
    });
    return false;
});

您可以使用简化版本(myJsRoutes从第 2 点开始):

myJsRoutes.controllers.Application.getItem(idToGet).ajax({
    success : function(data) { ... some code ... }
});

或者

myJsRoutes.controllers.Application.newItem().ajax({
    success : function(data) { ... some code ... }
});

等等...

  • 你不需要指定type: "POST"- JS 路由器会根据conf/routes规则使用正确的方法
  • 您可以使用纯 JS 中的语法id将记录(或其他参数)设置为GETPUT(或其他方法)routes-like
  • 如果你的路由规则包含所有必需的参数,你真的可以最小化你的 JS:

对于路线:

GET   /some/:a/:b/:c    controllers.Application.getABC(a: String, b: Integer, c: String)

JS:

myJsRoutes.controllers.Application.getABC("a", 1, "b" ).ajax({});
不是每个人都想使用 CoffeScript .. 而这就是这个官方文档附带的内容。
2021-03-23 05:02:09
另外,马库斯只是一个简单的问题,如果在我的操作中我进行了一些服务器端验证,然后返回 badRequest("Incorrect data sent"); 成功后,我还在我的 javascript 中添加了错误捕获: error : function(data) { setError('Make call failed'); 我如何访问我传递的字符串。当我将错误消息放入接收中时,我得到结果“对象 [对象]”。或者你知道我调试/检查这些信息的方法吗?
2021-03-24 05:02:09
官方文档中的javascript路由:playframework.com/documentation/2.1.1/JavaGuide6
2021-04-03 05:02:09
@biesior 我从答案中不明白的一件事是url : '@routes.Application.getItem()',理论上的 ajax 调用是否应该有效。我在这里尝试过,但没有,播放指责缺少参数。为什么我想问的原因是因为我想以类似的方式与它的jqGrid相结合,以什么做的这里
2021-04-12 05:02:09
非常感谢马库斯。我确实看过 zen 任务示例,但因为我刚刚回到网络开发,所以刷新了我的 html、css、javascript 知识。当那个例子是在咖啡脚本中完成时,它让我有点失望。当我尝试它时,我无法让它工作。
2021-04-13 05:02:09

我喜欢“老好”的简单方法:

1在页面中,使用JQuery,

在一些偶数处理程序中

 $.get('/giveme', {'arg': value}, function(data) {

                                    window.alert(data);

                                  }
 );

2在服务器/播放端

2.1 路线: GET /giveme controllers.Application.giveme(arg)

2.2 Scala 动作:

object Application extends Controller { 

      def giveme(arg:String) = Action {
        Ok(Json.toJson("hello," + arg ))
      }

    }
我可以在function(data). 喜欢function(data, data1)
2021-03-17 05:02:09

有什么需要注意的......打电话时

Routes.javascriptRouter("myJsRoutes",

路由是从 play.Routes 导入的,而不是 play.api.Routes

当我实现这段代码时出现错误,因为我认为它来自 api(显然我错了)。除此之外,一切都很好~!!

有一个更简单的解决方案,使用嵌入式路由器来生成 Javascript 路由器。您可以使用@javascriptRouterhelper 指令生成 Javascript 路由器,将以下代码放置在您的 html 页头标记内(可能在主装饰模板内)

<head>
    <title>Saeed Title</title>
    <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
    <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
    <script src="@routes.Assets.at("javascripts/jquery/v1.12.4/jquery.min.js")" type="text/javascript"></script>
    @helper.javascriptRouter("jsRoutes")(
        routes.javascript.MyController.getById,
        routes.javascript.MyController.getByName
    )
</head>

不要担心语法错误(在 Intellij 中)并且不要在操作名称后使用括号。现在您可以jsRoutes.controllers.MyController.getById(id)在您的 ajax 调用代码中使用。

$.ajax(jsRoutes.controllers.MyController.getById(id))
   .done( /*...*/ )
   .fail( /*...*/ );

或用于jsRoutes.controllers.MyController.getById(id).url获取网址。 更多信息

Marcus 的回答非常好,因此遇到此问题的其他任何人都应该能够使用它。

我确实遇到了一个问题,但在尝试让它发挥作用时,我花了一点时间才开始工作。当我发出 ajax 请求时,它路由到了错误的方法。

这是因为在我的路由文件中我有以下内容:

POST    /                           controllers.Application.makeCall()
POST    /                           controllers.Application.saveDefaultPhoneForUser(handset : String)

通过具有相同位置的两个 post 方法 /。它似乎总是去打电话。所以只是给任何人的一个提示,不要这样做,否则它将无法工作。

我只需要将其更改为:

POST    /                           controllers.Application.makeCall()
POST    /saveDefaultPhoneForUser    controllers.Application.saveDefaultPhoneForUser(handset : String)

希望这可以帮助某人。

这是正常的,如果routes文件包含两个具有相同方法和路径的规则,则只会使用第一个。
2021-03-31 05:02:09