如何使 Rails.ajax(...) 在所有页面上工作?
Posted
技术标签:
【中文标题】如何使 Rails.ajax(...) 在所有页面上工作?【英文标题】:How to make Rails.ajax(...) work on all page? 【发布时间】:2021-07-31 19:57:49 【问题描述】:您好,我正在尝试使用 Rails 6.1.3.1
上的 sweet alert 2
库执行 HTTP DELETE
请求!当我尝试这样的事情时,它完美地工作see my other question about this issue:
<button script='
Swal.fire(
"Good job!",
"You clicked the button!",
"success"
)
location.pathname = "<%= home_about_path %>"; //redirect to About Page
'>TEST</button>
但这仅适用于 GET
请求。因此有人建议要实现另一种类型的请求(即DELETE
),我必须使用AJAX
。所以,我发现你可以使用Rails.ajax(...)
来执行异步javascript。但是当我添加以下代码时,我得到了错误:friends:22 Uncaught (in promise) ReferenceError: Rails is not defined
。
//dir: project-name/app/views/friends/index.html.erb
Swal.fire(
"Good job!",
"You clicked the button!",
"success"
)
Rails.ajax(
type: "GET",
url: "<%= home_about_path %>",
success: function(response) alert("succes Go to About Page") ,
error: function(response) alert("error :" + response)
);
因此,我在 project-name/app/javascript/packs/application.js
内部测试了 Rails.ajax(..)
,其中声明了 Rails
!当然下面的代码会导致无限循环。但这只是为了测试目的!它工作正常。该页面一次又一次地重定向到关于页面。
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
Rails.ajax(
type: 'GET',
url: '/home/about',
success: function(response) location.pathname = "/home/about" ,
error: function(response) alert('error delete' + response)
);
所以我的问题是为什么命令Rails.ajax()
会在它声明的地方工作,而不是在特定的页面/控制器上?如何告诉 Rails 向整个系统声明 Rails
var?
@Joel_Blum 的解决方案:
应用程序.js
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
window.Rails = Rails;
index.html.erb:
Swal.fire(
"Good job!",
"You clicked the button!",
"success"
)
var redirect = '<%= friends_path %>';
redirect += '/<%= friend.id %>';
Rails.ajax(
type: 'DELETE',
url: redirect,
success: function(response)
//Friend has been deleted!
,
error: function(response)
//Error with Ajax
alert('error delete' + response)
);
【问题讨论】:
这是因为您放置在视图中的javascript(称为内联javascript)没有被webpacker / assets pipeline 编译,它不知道您系统中的其他javascript。 好的,我明白了,但是有没有办法连接这个。既然Rails
是在系统某处声明的,那么如何让内联JavaScript知道在哪里可以找到那个名字呢?
请记住,视图中的 javascript 不能使用 es6 语法或导入,通常最好不要经常这样做。您可以将所有 javascript 放在 application.js 中,只需注册一个 click 事件处理程序并在那里触发请求。
这是@max 建议的吗?
是的。您还可以通过 data-type="JSON"
将 Rails UJS 处理程序与其他请求类型(如 json)一起使用
【参考方案1】:
有几种方法可以解决这个问题。 您要问的基本上是如何使 Rails 对象成为全局对象,而不必使用模块导入。
import Rails from "@rails/ujs";
window.Rails = Rails;
应该照顾它或通过webpack as described in this answer
【讨论】:
感谢您的回答!现在工作得很好【参考方案2】:要向 Rails 应用发送 DELETE 请求,您将发送:
使用 HTTP 方法DELETE
的请求。现代浏览器在发送 XHR (ajax) 请求时可以做到这一点。
或带有参数_method=DELETE
的POST请求。
如果您想在用户单击要setup an event handler 的元素时触发 ajax 调用。这应该在您的 application.js
中完成,而不是内联:
document.addEventListener('click', function(e)
if (!e.target.matches('.my_special_button'))
return false;
Rails.ajax(
type: 'DELETE',
url: '/home/about',
success: function(response) location.pathname = "/home/about" ,
error: function(response) alert('error delete' + response)
);
);
您的代码将在文件加载后立即触发 ajax 请求。
Rails UJS 允许您通过向按钮本身添加数据属性来发送 Ajax 请求。
<button data-remote="true" data-method="DELETE" data-url="/home/about">TEST</button>
然后您可以使用 js.erb 模板,该模板已评估并触发 当 ajax 请求完成时:
# app/views/pages/about.js.erb
Swal.fire(
"Good job!",
"You clicked the button!",
"success"
)
location.pathname = "<%= home_about_path %>"; //redirect to About Page
Rails UJS 默认发送 Application/Javascript
mime 类型的 ajax 请求。
或者使用 JSON 等其他类型并监听 Rails UJS ajax events:
<button data-remote="true" data-method="DELETE" data-url="/home/about" class="my_special_button">TEST</button>
document.addEventListener("ajax:success", (event) =>
const [data, status, xhr] = event.detail;
if (!e.target.matches('.my_special_button'))
return false;
Swal.fire(
"Good job!",
"You clicked the button!",
"success"
)
location.pathname = "/home/about";
);
【讨论】:
是的,你可以使用全局变量和内联 JS,但作为开发人员,你真的只是把事情弄得一团糟,耽误了自己的进步。以上是关于如何使 Rails.ajax(...) 在所有页面上工作?的主要内容,如果未能解决你的问题,请参考以下文章