Play 2.x:如何使用普通按钮发出 AJAX 请求
Posted
技术标签:
【中文标题】Play 2.x:如何使用普通按钮发出 AJAX 请求【英文标题】:Play 2.x: How to make an AJAX request with a common button 【发布时间】:2012-06-23 09:16:49 【问题描述】:所以我之前已经成功地让 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;
);
我确信有办法做到这一点,但我只是没有运气找到任何东西。
【问题讨论】:
【参考方案1】:对于这项工作,您应该使用javascriptRoutes
,因为它会根据您的 routes.conf 生成正确的 JS 路径。您可以在 Zentask sample 中找到使用示例
无论如何,现在您可以通过将 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 中使用路由来获取正确的路径,而无需指定 url
和 type
。例如,而不是:
$('.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中使用routes-like
语法将记录(或其他参数)的id
设置为GET
或PUT
(或其他方法)
如果您的路由规则包含所有必需的参数,您可以真正最小化您的 JS:
路线:
GET /some/:a/:b/:c controllers.Application.getABC(a: String, b: Integer, c: String)
JS:
myJsRoutes.controllers.Application.getABC("a", 1, "b" ).ajax();
【讨论】:
非常感谢马库斯。我确实看过 zen 任务示例,但由于我刚刚回到 web 开发,所以刷新了我的 html、css、javascript 知识。当那个例子用咖啡脚本完成时,它让我有点反感。当我尝试它时,我无法让它工作。 如果在我的操作中我做了一些服务器端验证然后返回 badRequest("Incorrect data sent");成功后,我还在我的 javascript 中添加了错误捕获:error : function(data) setError('Make call failed');我如何访问我传递的字符串。当我将错误消息放入接收中时,我得到结果“对象 [对象]”。或者您知道我可以调试/检查这些信息的方法吗? 官方文档中的javascript路由:playframework.com/documentation/2.1.1/JavaGuide6 不是每个人都愿意使用 CoffeScript.. 这就是官方文档的内容。 @biesior 我从答案中不明白的一件事是,使用url : '@routes.Application.getItem()',
的ajax 调用理论上是否应该有效。我在这里尝试过,但没有,play 指责该论点缺失。我问的原因是因为我正在考虑以类似于here 的方式将它与 jqGrid 结合起来【参考方案2】:
我喜欢“老好”简单的方式:
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)
。【参考方案3】:
打电话时要注意的事情……
Routes.javascriptRouter("myJsRoutes",
Routes 是从 play.Routes 导入的,而不是 play.api.Routes
我在实现这段代码时出错,因为我认为它来自 api(显然我错了)。 除此之外,一切都很好~!!
【讨论】:
【参考方案4】:有一个更简单的解决方案,使用嵌入式路由器生成 Javascript 路由器。您可以使用@javascriptRouter
helper 指令生成 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 中),也不要在操作名称后使用括号。
现在您可以在 ajax 调用代码中使用jsRoutes.controllers.MyController.getById(id)
。
$.ajax(jsRoutes.controllers.MyController.getById(id))
.done( /*...*/ )
.fail( /*...*/ );
或使用jsRoutes.controllers.MyController.getById(id).url
获取网址。
more information.
【讨论】:
【参考方案5】: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
文件中包含两条规则,方法和路径相同,只会使用第一个。以上是关于Play 2.x:如何使用普通按钮发出 AJAX 请求的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Play 2.2.x 的 dist 任务中禁用 ScalaDoc 生成(使用 project/build.scala)?
如何在构建定义中更改 Play 2.3.x 中的默认端口 9000?
在发出初始ajax请求后,Ajax请求无法发送 - 试图找出导致冲突的原因