我正在尝试将Rails 5.1.7应用程序升级到5.2.0。网站上的一些表单被升级打破了。表单的模板如下所示:
<%= form_with model: record, url: client_field_value_path(@dataset, record), remote: true do |form| %>
<%= the form contents %>
<% end %>我认为表单中唯一相关的部分是它使用remote: true。我发现在Rails 5.2中,remote: true被更改为form_with助手的默认设置。我相信这是用不显眼的javascript实现的,但我对ujs的理解不是很好。
表单是在不重新加载页面的情况下提交的,页面中的状态更改由ajax侦听器处理。我们使用jquery -客户端代码包括行:
$(this.form).trigger('submit');它正在执行本地提交,而不是远程提交。这样页面就会刷新,JSON响应就会呈现出来。我发现针对rails-ujs的问题看起来是相关的,他们建议用
form = document.querySelector('form');
form.dispatchEvent(new Event('submit', {bubbles: true}));或者,用rails-ujs,
form = document.querySelector('form');
Rails.fire(form, 'submit');我已将rails-ujs添加到application.js文件中:
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
// ....
//= require jquery
//= require jquery_ujs
//= require rails-ujs
// ....(jquery和jquery_ujs已经存在了)。我尝试了上述两种建议,但它们似乎都没有触发表单的提交。我真的被困住了!如果有更多的细节我可以提供,请问。我不太理解ujs的情况,所以我有点迷路了。
编辑:完整的保存调用--这是在单击“保存”按钮时触发的(但该按钮不是<input type=submit>,它只是一个样式的按钮)。
save(event) {
if( event ) {
event.preventDefault();
event.stopPropagation();
}
this.container.addClass('saving');
// this.form.submit();
Rails.fire(this.form[0], 'submit');
this.container.find(".field-controls button").prop('disabled', true);
}更新:,我已经设法让它正常工作了。我非常感谢您能帮助我理解以下更改的来源,以及应用程序配置中是否出现了一些问题,这使得它变得比必要的更难。
remote: true更改为local: false。data-remote=true属性就不会在HTML中设置。local: false,我就会进入控制台:$('form[data-remote=true]').length
0Rails.application.config.action_view.form_with_generates_remote_forms配置。这个值是控制台中我的nil。我找不到它被覆盖的任何地方。rails-ujs并删除了jquery_ujs。rails-ujs,以便定义Rails (下一步需要)。rails-ujs时,我收到了一个JS警告:应该删除jquery_ujs。我认为这是包括在jquery-rails宝石-我也安全地删除它吗?this.form.submit()改为Rails.fire(this.form[0], 'submit')。$(form).submit()的任何变体都执行本地提交,而不是远程提交。ajax:success处理程序的签名。 form.on('ajax:success', (event, response, status) => {
$.each(response, (i, key) => {
do_stuff();
});
});至
form.on('ajax:success', (event) => {
const [response, _status, _xhr] = event.detail;
$.each(response, (i, key) => {
do_stuff();
});
});同样,我想这是因为事件是由rails-ujs处理的,而不是由jquery处理的,但是.为什么?你怎么会知道?
发布于 2021-03-08 21:54:20
好吧,我想了几件事。
本地: false而不是remote: true
首先,form_with不再有remote选项了,它被称为本地:
<%= form_with model: record, url: client_field_value_path(@dataset, record), local: false do |form| %>
<%= the form contents %>
<% end %>而且,您应该能够跳过这一点,因为这是默认的。您可以通过删除它,然后检查指向此表单视图的路由的html标记来确认这一点,您应该可以在表单标记中看到data-remote="true"。这可能不是问题所在。
您的jQuery代码在哪里?
通常,ujs的工作方式是在视图目录中有一个名为create.js.erb的文件。当您提交表单时,该文件中的JS将运行,您将能够在该模板中使用erb标记向js添加动态内容。例如,您可以在这里使用render来呈现一个部分,并传入控制器中定义的实例变量。
当然,如果您已经单独设置了所有的javascript,并且它应该只在使用javascript时才能正常工作,那么它就不再是UJS。UJS代表不引人注目的javascript。这个想法是,javascript增强了功能,而不是取代它。这意味着,如果您的javascript由于某种原因没有加载,表单仍将提交并正常工作,而不需要使用javascript。这可能不是你的应用程序的情况,这很好,但知道提供一个更好的答案是有用的。
UJS模式的工作方式依赖于一些控制器代码。因此,控制器中有一个respond_to块,可以同时响应html请求和js请求。如果表单是远程的,那么它将在与控制器操作匹配的文件中运行javascript。例如,
def create
@record = Record.new(record_params)
respond_to do |format|
if @record.save
format.html { redirect_to records_path }
format.js {}
else
format.html { render :new }
format.js { render :error }
end
end
end
end发布于 2021-03-09 20:41:20
我现在明白这个问题了!我以前很困惑。
答案
出于某种原因(我仍然不明白),
Rails.application.config.action_view.form_with_generates_remote_forms升级后未设置。由于未设置data-remote="true"属性,所以jquery没有使用AJAX提交表单。在我的初始化中将这个配置变量设置为true解决了这个问题。
离题
想到rails-ujs是jquery-ujs的替代品,我感到非常困惑。事实并非如此。他们的工作方式完全不同!jquery拦截通过jquery调用的事件,以便(例如)获取与AJAX一起提交的远程表单。通过创建自己的事件并使用Rails.fire调用它们,rails-ujs具有相同的功能效果。他们在一起打得不好!
我在添加rails-ujs之后遇到的所有困惑都源于这样一个事实:它们基本上是具有不同API的不同库。
https://stackoverflow.com/questions/66534265
复制相似问题