Rails中form_tag结合Ajax失效排查:实现选中课程TD删除
解决Rails中form_tag配合Ajax移除课程的问题
我来帮你排查下这个Ajax配合form_tag的问题,看了你的代码,有几个关键地方需要调整,咱们一步步来:
1. 先修正视图里的低级语法错误
你在_courses.html.erb里写的<td">多了一个引号,这会导致HTML结构异常,直接改成<td>就行:
<%= form_tag delete_drafts_path, remote: true do %> <%= submit_tag 'Update', class: 'course-container-new-row-button' %> <% @courses_drafts.each do |course| %> <tr> <td> <div class="check-button"> <label> <%= check_box_tag "approved_ids[]", course.id, nil %> <span> <i class="fa fa-check" aria-hidden="true"></i> </span> </label> </div> </td> </tr> <% end %> <% end %>
2. 控制器要真正处理删除逻辑呀
现在你的courses_controller.rb里的courses方法只是在查询pending的课程,完全没处理提交过来的复选框ID,也没执行删除操作。得加上POST请求的处理逻辑,还要把删除的ID传给JS模板:
def courses # 处理提交过来的删除请求 if request.post? # 拿到勾选的课程ID,为空的话设成空数组 @deleted_ids = params[:approved_ids] || [] # 删除对应的草稿课程 Course.where(id: @deleted_ids).destroy_all end @courses_pending = Course.where(activity: 2).page(params[:page]).order('day ASC') respond_to do |format| format.js format.html end end
3. JS模板的选择器逻辑完全错了
原来的JS里$(this).closest('td')根本找不到对应的元素,因为提交按钮是在form根节点下,和tr是同级关系,不是嵌套在td里。咱们要根据删除的ID来定位对应的行,修改courses.js.erb:
// 遍历所有被删除的课程ID,找到对应的复选框所在的tr,然后淡出移除 <% @deleted_ids.each do |id| %> $('input[value="<%= id %>"]').closest('tr').fadeOut(function() { $(this).remove(); // 动画结束后彻底移除元素 }); <% end %>
如果你只想移除对应的<td>而不是整行,把closest('tr')改成closest('td')就行。
4. 最后确认路由没问题
你的路由配置是对的,确保是POST请求就好:
post :delete_drafts, to: "courses#courses", as: :delete_drafts
额外要注意的小细节
- 确保你的项目里已经引入了jQuery,Rails UJS依赖它才能正常处理
remote: true的请求(如果是Rails 6+,可能需要在application.js里手动导入) - 打开浏览器控制台,看看有没有JS报错,比如找不到jQuery或者选择器无效的问题
- 可以在控制器里加一行
logger.debug params.inspect,然后看日志确认approved_ids有没有正确传过来
这样调整后,勾选复选框点击提交,控制器会删除对应的课程,JS模板会找到对应的行(或td)并淡出移除,应该就能正常工作了。
内容的提问来源于stack exchange,提问作者Digital Spartan
相关产品推荐
相关产品推荐

