Ajax调用后Rails实例变量不更新 ISBN输入值回滚问题
看起来你遇到的核心问题是:每次AJAX查询成功后,你用返回的_isbn_lookup_result局部视图替换了容器内容,但这个视图里的ISBN输入框硬绑定了@isbn_lookup_result[:isbn]——也就是上一次查询到的ISBN值。所以哪怕你手动修改了输入框内容,新渲染的HTML又会把它重置回之前的ISBN,导致输入值回滚。
下面是两种最直接的解决思路,优先推荐第一种,因为结构更清晰,能从根源避免问题:
方案一:拆分视图结构(最优解)
把ISBN输入框和图书信息展示部分拆分开,让AJAX只更新图书信息区域,不碰输入框本身。这样输入框永远不会被重新渲染,自然不会出现值回滚的问题。
1. 修改主视图_form.html.erb
把ISBN输入框留在主视图里,单独留出图书信息的容器:
<!-- 保留ISBN输入框在主视图 --> <div class="form-group"> <%= text_field_tag :isbn, nil, class: "form-control", id: "isbn_field", placeholder: "ISBN (10 or 13 digits - no dashes)", autofocus: true %> </div> <!-- 专门用来展示图书信息的容器 --> <div id="isbn-lookup-results-container"></div> <div id="form-unfilled">...</div>
2. 重构_isbn_lookup_result.html.erb
只保留图书信息的渲染逻辑,去掉form和ISBN输入框:
<div class="book-details"> <h4><%= @isbn_lookup_result[:title] %></h4> <p><strong>作者:</strong> <%= @isbn_lookup_result[:author] %></p> <!-- 其他图书信息(出版社、出版日期等) --> <!-- 如果需要把标准化后的ISBN存入表单用于后续提交,可以加隐藏域 --> <%= hidden_field_tag :listing[isbn], @isbn_lookup_result[:isbn] %> </div>
3. 保持JS逻辑不变
你的lookup.js.coffee代码不需要修改,因为它本来就是只更新#isbn-lookup-results-container的内容,现在这个容器里只有图书信息,不会影响到输入框。
方案二:不拆分视图,修改输入框的value绑定
如果不想调整视图结构,你可以让局部视图里的输入框显示用户当前输入的ISBN(而非查询返回的标准化ISBN),这样即使输入框被重新渲染,显示的也是用户正在编辑的内容。
修改_isbn_lookup_result.html.erb里的text_field:
<%= f.text_field :isbn, class: "form-control", id: "isbn_field", placeholder: "ISBN (10 or 13 digits - no dashes)", value: params[:isbn], autofocus: true %>
这里把value: @isbn_lookup_result[:isbn]换成了value: params[:isbn],也就是用户刚刚输入的原始值,这样重新渲染后输入框会保留用户的编辑内容。
不过这种方案有个小缺点:如果亚马逊返回了标准化的ISBN(比如用户输入带空格的ISBN,返回的是无空格的标准格式),输入框不会自动同步这个标准化值。如果需要这个特性,还是方案一更合适。
内容的提问来源于stack exchange,提问作者Jack Moody

