You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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中引入依赖:

  1. 执行yarn add jquery安装依赖
  2. 在app/javascript/application.js中添加import $ from 'jquery'
  3. 调整原有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效果一致)

仅需调整循环写法符合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:27:34