ruby-on-rails 如何将呈现部分onchange的select从rails6转换到rails7

htrmnn0y  于 2023-07-01  发布在  Ruby
关注(0)|答案(1)|浏览(123)

小心,我与haml不是erb工作!

在我的Rails 6应用程序中,我有一个选择。如果我改变了选择,页面的内容就改变了。
视图如下:

:javascript
  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.attr('rel'), {id: that.val(), jpeg_id: jpeg_id }, null, "script");
  });
  }

  });

%h1.text-center
  = "Example select"

%br
= select(:label, :id, Label.all.map {|u| [u.description, u.id]}.push(["Unknown", 0]),{ selected: 0 }, rel: "update_label_content")
%br
%br

#gallery
  =render partial: 'shared/gallery' , locals: {image_objects: @image_objects, jpeg: @jpeg, current_label: 0 }

:javascript
  $("#label_id").subSelectWithAjax();

我知道这段代码有点难看,但最后一行使select中的更改调用subSelectWithAjax。此函数发布到控制器中的“update_label_content”。
控制器代码如下所示:

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

此函数呈现的视图(update_label_content.js.haml)如下所示:

$("#gallery").html("");
$('#gallery').append("#{escape_javascript(render partial: 'shared/gallery' , locals: {image_objects: @image_objects, jpeg: @jpeg }) }");

_gallery.html.haml看起来像这样:
这段代码中有一些lightbox-gallery的东西。你应该忽略这个!

%div{ class: "lightbox-gallery"}
    .container
      .row.photos
        -for obj in image_objects
          - 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 )

如何将此代码移植到Rails 7?

zpgglvta

zpgglvta1#

这就是我出来的地方。
首先我不得不读关于hotwire的书。这包括两个部分,涡轮和刺激。您应该先阅读hotwire的文档。
我分步骤给出了答案:

第一步

我在JavaScript/controller目录中创建了一个controller文件,名为label_bin_controller.js:

import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="label-bin"
export default class extends Controller {

  connect() {
    console.log("is it connecting ?");
  }
}

第二步

从旧的观点来看,我:
1.删除所有javacode
1.在代码周围添加了一个div和一个data-controller label-bin。
1.添加了一个隐藏的文件来获取jpeg_id(这可以用不同的方式完成)
1.删除了“rel”并在select中添加了一个data-action

-# change 2
%div{ "data-controller": "label-bin" }   
  %h1.text-center
    = "Example select"
  -# change 3
  %input{ type: :hidden, id: :jpeg_id, value: @jpeg.id }
  %br
  -# change 4
    = select(:label, :id, Label.all.map {|u| [u.description, u.id]}.push(["Unknown", 0]),{ selected: 0 }, { "data-action": "label-bin#change" })
  %br
  %br

  #gallery
    =render partial: 'shared/gallery' , locals: {image_objects: @image_objects, jpeg: @jpeg, current_label: 0 }

为了测试,我们可以加载视图,在控制台浏览器调试控制台中应该有消息“它正在连接吗?“从label_bin_controller.js。我发现奇怪的一件事是,你应该在代码中使用label-bin,但文件名为label_bin。

第三步

如果我们已经连接了控制器,我们可以添加change事件:

import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="label-bin"
export default class extends Controller {

  connect() {
    console.log("is it connecting ?");
  }

  change(event) {
    console.log("Change");
    var label_id = document.getElementById("label_id").value;
    var jpeg_id = document.getElementById("jpeg_id").value;
    const frame = document.getElementById('image_objects');
    frame.src="update_label_content?jpeg_id=" + jpeg_id + "&id=" + label_id;
    frame.reload();
  }

}

如果我们在浏览器中重新加载页面并更改选择,则应在刺激控制器中触发更改。您应该会在浏览器中看到控制台消息,并且还会收到对服务器端Rails控制器的调用。(获取请求)

第四步

我们必须在控制器action中添加一行代码,以使用turbo_stream渲染:

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
    # added line
    render turbo_stream: turbo_stream.replace(:image_objects, partial: "shared/gallery", locals: { image_objects: @image_objects })
  end

步骤5

你必须将你的_gallery部分嵌入到一个turbo-frame中。如上所述,有一些lightbox画廊和可拖动的代码,请忽略这一点!

%turbo-frame{ id: :image_objects }
    %div{ class: "lightbox-gallery"}
      .container
        .row.photos
          -for obj in image_objects
            - 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 )

我为自己记录了这些。我希望其他人能从中受益。我试着让它尽可能简单,但可能在这个过程中产生了一些错误。

相关问题