[英]Is there a way to render a js.erb after a fetch call?
In my Rails app, I want to render a js.erb partial after a fetch call and for some reasons I do not understand it does not work.在我的 Rails 应用程序中,我想在 fetch 调用后呈现 js.erb 部分,但由于某些原因我不明白它不起作用。 If you can help me, it would be great.
如果你能帮助我,那就太好了。
In a view, an event trigger this function that basically do a fetch request:在一个视图中,一个事件触发了这个函数,它基本上是一个 fetch 请求:
function updateState(id, state){
const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
.content.value;
fetch(window.location.origin + "/update_state", {
method: "POST",
headers: {
'Accept': "JS",
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({'id': id, 'state': state}),
credentials: "same-origin"
})
}
Then in my controller:然后在我的控制器中:
def update_state
@model = Model.find(params[:id])
authorize @model
@model.update(state: params[:state])
respond_to do |format|
format.html { redirect_to xxx }
format.js
end
end
In my js.erb files:在我的 js.erb 文件中:
console.log('hello');
However, in that case, I get an error from the server: ActionController::UnknownFormat at the line 'respond_to do |format|但是,在这种情况下,我从服务器收到一个错误: ActionController::UnknownFormat 在 'respond_to do |format| 行I have the feeling that the server do not understand the header of the fetch: 'Accept': "JS"
我有一种感觉,服务器不理解 fetch 的标题:'Accept':“JS”
When I look at the logs of the server:当我查看服务器的日志时:
Started POST "/update_state" for 127.0.0.1 at 2019-04-04 11:22:49 +0200
Processing by ModelsController#update_state as JS
But I think that Rails does not recognize it.但我认为 Rails 无法识别它。 How do I do?
我该怎么办?
I tried also this in the controller:我也在控制器中尝试过这个:
def update_state
@model = Model.find(params[:id])
authorize @model
@model.update(state: params[:state])
render 'update_state.js', layout: false
end
Which does not fire errors.这不会触发错误。 I received in the client side the js.erb.
我在客户端收到了 js.erb。 However, it is not executed (console.log does not execute).
但是,它不执行(console.log 不执行)。
Do you have any idea?你有什么主意吗? Thank a lot for your help.
非常感谢您的帮助。
I manage the other way around.我反过来管理。 I never succeded with js.erb.
我从未成功使用 js.erb。
So I use a fetch call with a response in text:因此,我使用带有文本响应的 fetch 调用:
function updateState(id, state){
const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
.content.value;
fetch(window.location.origin + "/update_state", {
method: "POST",
headers: {
'Accept': "JS",
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({'id': id, 'state': state}),
credentials: "same-origin"
}).then(response => response.text())
.then(data => {
div.inserAdjacentHTML('XXX', data);
});
}
Then in the controller/action:然后在控制器/动作中:
def update_state
@model = Model.find(params[:id])
authorize @model
@model.update(state: params[:state])
render 'update_state.js', layout: false, content_type: "text/plain"
end
That way, it works.这样,它就起作用了。 Hope it helps.
希望能帮助到你。
Edit : look at the edit for a fully working solution on triggering manually a .js.erb file.编辑:查看有关手动触发 .js.erb 文件的完整工作解决方案的编辑。
Had the same issue and there are actually two problems here.有同样的问题,实际上这里有两个问题。 Your are right, your headers are not.
你是对的,你的标题不是。 These headers to trigger the
.js.erb
worked for me and seems pretty right :这些触发
.js.erb
标头对我.js.erb
,看起来很正确:
'dataType': 'json',
'contentType': 'application/json; charset=utf-8',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': - your CSRF method to get the token -
But secondly to trigger the js response, your respond_to
block :但其次要触发 js 响应,您的
respond_to
块:
respond_to do |format|
format.html { redirect_to xxx }
format.js
end
Has to have the format.js first.必须先有 format.js。 As rails has a response for the HTML it will respond with HTML first and seems to not even look for the next format block.
由于 rails 对 HTML 有响应,它将首先以 HTML 响应,并且似乎甚至不寻找下一个格式块。
respond_to do |format|
format.js
format.html { redirect_to xxx }
end
Hope it helps :-)希望能帮助到你 :-)
Hey, long time no see !嘿,好久不见! The same issue happened to me again and my own previous reply wasn't solving the issue.
同样的问题再次发生在我身上,我自己之前的回复没有解决问题。 Like you, the .js.erb file was rendered but nothing happened and the
console.log
was not displayed.和你一样,.js.erb 文件被渲染了,但什么也没发生,
console.log
也没有显示。 So I created a link_to
with remote: true
that triggered my .js.erb
file and compared the requests.所以我创建了一个带有
remote: true
的link_to
触发了我的.js.erb
文件并比较了请求。 Everything was the same except one thing : the type of the request.除了一件事之外,一切都相同:请求的类型。 One was a fetch, the other was an
xhr
.一个是 fetch ,另一个是
xhr
。 It appears that the .js.erb
files are triggered only by the xhr
requests.似乎
.js.erb
文件仅由xhr
请求触发。 So the solution is to build an old xhr
request instead of a fetch, like this :因此,解决方案是构建一个旧的
xhr
请求而不是 fetch,如下所示:
const url = 'your_custom_path' // Build the url to fetch
const csrf = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
let xhr = new XMLHttpRequest();
// Will be a GET request here
xhr.open('GET', url, false);
// Setting the headers
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('X-CSRF-Token', csrf);
xhr.setRequestHeader('dataType', 'script');
// What to do with the response
xhr.onload = function() {
let responseObj = xhr.response
eval(responseObj) // You need to eval() manually the response for it to be executed
}
// Sending the request
xhr.send()
Hope it helps, even some months later!希望它有所帮助,即使是几个月后! ;)
;)
I ran into this issue in Rails 6 using fetch.我在 Rails 6 中使用 fetch 遇到了这个问题。 My issue was solved by simply placing format.js above format.html.
我的问题是通过简单地将 format.js 放在 format.html 之上来解决的。 Thanks @holino.
谢谢@holino。 The following fetch works.
以下提取有效。
fetch(event.currentTarget.dataset.destroyPath, {
method: 'DELETE',
dataType: 'script',
credentials: 'include',
headers: {
'X-CSRF-Token': csrf
},
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.