如何将Rails 6中Onchange局部渲染的Select迁移至Rails 7(HAML环境)
将Rails 6的AJAX下拉选择功能迁移到Rails 7
一、核心思路:改用Rails 7默认的Turbo(替代jQuery)
Rails 7默认集成Turbo,无需依赖jQuery即可实现AJAX页面更新,这是官方推荐的方案,代码更简洁且符合框架生态。
二、主视图(HAML)改造
替换原有jQuery代码和独立select标签,用form包裹下拉框,利用Turbo自动处理AJAX请求:
%h1.text-center = "Example select" %br = form_tag update_label_content_path, method: :post, data: { turbo_stream: true } do = select_tag :label_id, options_for_select(Label.all.map { |u| [u.description, u.id] }.push(["Unknown", 0]), selected: 0), name: "id" = hidden_field_tag :jpeg_id, @jpeg.id %br %br #gallery = render partial: 'shared/gallery', locals: { image_objects: @image_objects, jpeg: @jpeg, current_label: 0 }
说明:
- 用
form_tag包裹下拉框,指定提交路径与POST方法 data: { turbo_stream: true }告诉Turbo以AJAX方式提交请求,并接收Turbo Stream响应- 新增
hidden_field_tag传递jpeg_id,替代原JS中硬编码参数的方式 - 用
options_for_select简化选项生成逻辑,符合Rails最佳实践
如果一定要保留jQuery(不推荐),需先在Rails 7中引入依赖:
- 执行
yarn add jquery安装依赖 - 在
app/javascript/application.js中添加import $ from 'jquery' - 调整原有JS代码适配Turbo页面加载事件:
:javascript document.addEventListener('turbo:load', function() { jQuery.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader("Accept", "text/javascript") } }); $.fn.subSelectWithAjax = function() { var that = this; var jpeg_id = "#{@jpeg.id}"; this.change(function() { $.post(that.data('rel'), { id: that.val(), jpeg_id: jpeg_id }, null, "script"); }); } $("#label_id").subSelectWithAjax(); }); %h1.text-center = "Example select" %br = select(:label, :id, Label.all.map {|u| [u.description, u.id]}.push(["Unknown", 0]),{ selected: 0 }, data: { rel: update_label_content_path }) %br %br #gallery = render partial: 'shared/gallery' , locals: {image_objects: @image_objects, jpeg: @jpeg, current_label: 0 }
(注意将rel属性改为符合HTML5规范的data-rel,并直接传入路径而非字符串)
三、控制器代码调整
原有逻辑基本无需修改,只需确保参数接收正常:
def update_label_content @jpeg = Jpeg.find(params[:jpeg_id]) if params[:id].to_i == 0 @image_objects = @jpeg.image_objects.where("label_id=0 or label_id is null") else @image_objects = @jpeg.image_objects.where(label_id: params[:id]) end end
四、响应模板改造
方式1:使用Turbo Stream(推荐)
创建app/views/[对应控制器名]/update_label_content.turbo_stream.haml,Turbo会自动完成DOM替换:
= turbo_stream.update "gallery" do = render partial: 'shared/gallery', locals: { image_objects: @image_objects, jpeg: @jpeg }
方式2:保留原有JS响应(兼容旧逻辑)
修改update_label_content.js.haml简化代码:
$("#gallery").html("#{escape_javascript(render partial: 'shared/gallery' , locals: {image_objects: @image_objects, jpeg: @jpeg }) }");
(直接用.html覆盖内容,和原清空再append效果一致)
五、局部视图_gallery.html.haml优化(可选)
仅需调整循环写法符合Ruby规范,功能逻辑无需修改:
%div{ class: "lightbox-gallery"} .container .row.photos - image_objects.each do |obj| - if obj.mask_image.present? .col-sm-6.col-md-2.text-center.item %a{ href: obj.mask_image.url, "data-toggle": :lightbox, "data-type": "image", "data-gallery": "example-gallery", class: "img-fluid" } = image_tag(obj.mask_image, height: "200", class: "draggable", id: obj.id )
内容的提问来源于stack exchange,提问作者me1960
相关产品推荐
相关产品推荐

