提问人:nimmolo 提问时间:2/14/2023 最后编辑:Ryan Mnimmolo 更新时间:2/18/2023 访问量:139
Rails 6 form_with远程 UJS,绑定额外的处理程序来选择或提交
Rails 6 form_with remote UJS, bind extra handler to select or submit
问:
在我的 Rails 应用程序中,我有一个用于对各种“帖子”标题进行投票的功能。该表单有一个元素,并远程提交到 using .我想以正常方式处理响应,在接收请求的控制器中,使用 .form
select
VotesController
rails-ujs
respond_to do |format|
一种选择是添加到构建器中,正如其他答案所建议的那样。{:onchange=>'$(this.form).submit();'}
f.select
但是,由于表单提交大约需要 8 秒,因此我想将我自己的处理程序添加到 或 (哪个事件对我来说无关紧要)select
onchange
form
onsubmit
- 禁用同一页面上的所有其他表单
- 显示一个模态,说明我们为什么要禁用其他表单
- 每个用户只允许一次“收藏”投票(降级之前对其他游戏的投票)
- 在 Select 中存储一些数据属性以供以后处理
我遇到的问题是
- 如果我将我的额外处理程序绑定到 select 事件,我可以通过 native 触发提交,但浏览器会询问我是否要离开当前页面。我可以通过将我自己的AJAX调用添加到我的处理程序来解决此问题,但我正在尝试使用默认的Rails控制器并处理提交。我只想添加一个额外的处理程序来在缓慢的响应到达之前更改 DOM。
change
rails-ujs
rails-ujs
- 如果我将额外的处理程序绑定到表单事件,则表单不会提交,并且绑定对 DOM 中的元素没有任何影响,尽管没有控制台错误。
submit
这是我的代码:
# partial appears on PostsController#show
# there are several of these on the page, for voting on post titles
<%= form_with(model: @vote, url: naming_vote_path(naming_id: naming.id),
method: :patch, local: false, id: "cast_vote_#{naming.id}",
class: "naming-vote-form") \
do |f| %>
<%= f.select(:value, menu, {},
{ class: "form-control w-100",
# onchange: "this.form.submit();", # works but does not allow further bindings
data: { role: "change_vote", id: naming.id } }) %>
<% end %>
$(document).ready(function () {
var change_vote_selects = function () {
return $("[data-role='change_vote']");
};
var attach_bindings = function () {
change_vote_selects().on("change", function (event) {
var _this = $(this);
var value = _this.val();
var naming_id = _this.data("id");
_haveVotesChanged = true;
// If setting vote to 3.0, go through all the rest and downgrade any
// old 3.0's to 2.0. Only one 3.0 vote is allowed. Also disable all
// the selects while the AJAX request is pending.
if (value == "3.0") {
change_vote_selects().each(function () {
var _this2 = $(this);
if (_this2.data("id") != naming_id && _this2.val() == "3.0") {
_this2.val("2.0");
}
_this2.attr("disabled", "disabled");
});
}
// modal printed in layout already, add text to it and activate
$('#naming_ajax_progress_caption').empty().append(
$("<span>").text(translations.show_namings_saving + "... "),
$("<span class='spinner-right mx-2'></span>")
);
$("#naming_ajax_progress").modal('show');
_this.parent().submit();
});
// Save initial value in case of error, when we'll need to revert.
change_vote_selects().each(function (event) {
var _this = $(this);
_this.data("old_value", _this.val());
_this.attr("disabled", null);
});
};
// Alert the user if they haven't saved data.
window.onbeforeunload = function () {
if (_haveVotesChanged && !_haveVotesBeenSaved)
return translations.show_namings_lose_changes;
}
attach_bindings();
});
答:
0赞
nimmolo
2/14/2023
#1
多亏了这个答案,我需要在表单上触发一个原生的 rails-ujs 提交,以远程提交。
$(document).ready(function () {
var change_vote_selects = function () {
return $("[data-role='change_vote']");
};
var attach_bindings = function () {
change_vote_selects().on("change", function (event) {
var _this = $(this);
var value = _this.val();
var naming_id = _this.data("id");
_haveVotesChanged = true;
// If setting vote to 3.0, go through all the rest and downgrade any
// old 3.0's to 2.0. Only one 3.0 vote is allowed. Also disable all
// the selects while the AJAX request is pending.
if (value == "3.0") {
change_vote_selects().each(function () {
var _this2 = $(this);
if (_this2.data("id") != naming_id && _this2.val() == "3.0") {
_this2.val("2.0");
}
_this2.attr("disabled", "disabled");
});
}
// modal printed in layout already, add text to it and activate
$('#naming_ajax_progress_caption').empty().append(
$("<span>").text(translations.show_namings_saving + "... "),
$("<span class='spinner-right mx-2'></span>")
);
$("#naming_ajax_progress").modal('show');
nativeFormEl = _this.parent()[0]
Rails.fire(nativeFormEl, 'submit')
});
// Save initial value in case of error, when we'll need to revert.
change_vote_selects().each(function (event) {
var _this = $(this);
_this.data("old_value", _this.val());
_this.attr("disabled", null);
});
};
// Alert the user if they haven't saved data.
window.onbeforeunload = function () {
if (_haveVotesChanged && !_haveVotesBeenSaved)
return translations.show_namings_lose_changes;
}
attach_bindings();
});
评论