Rails。在cocoon gem字段内预览图像

问题描述 投票:1回答:1

我有一个 simple form(product model) 而我也在使用 cocoon gem 对于 nested fields(attachments model) 我在该表格内有的。当我创建一个产品时,我使用 cocoon gem 嵌套字段,以便创建 attachments(images) 并将其关联到该产品。用户可以添加一个茧字段,并添加一个图像到该字段。我还在每个字段内有一个预览,这样用户就可以查看他们附加到该字段的图像。但唯一的问题是,预览只显示在第一个茧字段。如果我尝试添加一个图像到另一个茧字段,图像预览不出现在该字段内。我希望能够添加一个茧字段,然后将图像添加到该字段,并在该字段内查看该图像的预览。有什么想法可以让我改变我的代码,以实现上述目标?

enter image description here

这是我的设置。

<%= f.simple_fields_for :attachments do |attachment| %>
  <%= render 'products/attachment_fields', form: attachment  %>
<% end %>

<div class="links" id="add_attachment">
  <%= link_to_add_association raw('<i class="fas fa-plus"></i>'), f, :attachments, form_name: 'form'  %>
</div>

attachment_fields partial :

<div class="nested-fields">
  <div class="col-md-12">
    <div class="image-border">
      <div class="image-border-content">
        <div class="parent">
          <div class="image-content" id="divImageMediaPreview">
            <div class="font-awesome-image"><i class="far fa-image"></i></div>
          </div>
        </div>
        <label class="btn btn-light btn-sm" style="width: 100%;">
          Add a file!
          <span style="display:none;">
            <%= form.input :image, label: false, as: :file, input_html: { class:"custom-file-input", id: "ImageMedias" } %>
          </span>
        </label>
      </div>
    </div>
    <div class="links" style="margin-bottom: 10px;">
      <%= link_to_remove_association raw('<i class="far fa-trash-alt"></i> Remove'), form, class: "btn btn-light btn-sm", :style => "width: 100%; margin-top: -15px;" %>
    </div>
  </div>
</div>

图片预览。

$("#ImageMedias").change(function () {
    if (typeof (FileReader) != "undefined") {
        let dvPreview = $("#divImageMediaPreview");
        dvPreview.html("");
        $($(this)[0].files).each(function () {
            let file = $(this);
            let reader = new FileReader();
            reader.onload = function (e) {
                let img = $("<img />");
                img.attr("style", "width: 100%; height:auto;");
                img.attr("src", e.target.result);
                dvPreview.append(img);
            }
            reader.readAsDataURL(file[0]);
        });
    } else {
        alert("This browser does not support HTML5 FileReader.");
    }
});

更新1

我对@nathanvda的回答稍作调整,就成功了。但我有一个小问题。如果我一次只添加一个字段,每个字段都会出现预览,但如果我添加多个字段,就会出现下图中的问题。有什么办法可以解决这个问题吗?

enter image description here

这是我使用的确切代码。

<div class="nested-fields">
  <div class="col-md-12">
    <div class="image-border">
      <div class="image-border-content">
        <div class="parent">
          <div class="image-content image-media-preview">
            <div class="font-awesome-image"><i class="far fa-image"></i></div>
          </div>
        </div>
        <label class="btn btn-light btn-sm" style="width: 100%;">
          Add a file!
          <span style="display:none;">
        <%= form.input :image, label: false, as: :file, input_html: { class:"custom-file-input" } %>
          </span>
        </label>    
      </div>
    </div>
    <div class="links" id="remove_attachment" style="margin-bottom: 10px;">
      <%= link_to_remove_association raw('<i class="far fa-trash-alt"></i> Remove'), form, class: "btn btn-light btn-sm", :style => "width: 100%; margin-top: -15px;" %>
    </div>
  </div>
</div>




$(function() {
    $('input[type=file]').change(function(){
        if (typeof (FileReader) != "undefined") {
            let dvPreview = $(this).parents(".image-border").find(".image-media-preview");
            dvPreview.html("");
            $($(this)[0].files).each(function () {
                let file = $(this);
                let reader = new FileReader();
                reader.onload = function (e) {
                    let img = $("<img />");
                    img.attr("style", "width: 100%; height:auto;");
                    img.attr("src", e.target.result);
                        dvPreview.append(img);
                }
                reader.readAsDataURL(file[0]);
            });
        } else {
            alert("This browser does not support HTML5 FileReader.");
        }
    })
});
javascript jquery ruby-on-rails cocoon-gem
1个回答
2
投票

你使用一个id为 #divImageMediaPreview这意味着html希望这个元素在页面上只出现一次。你需要给这个元素一个类,然后搜索最接近的实例。

例如,在你的视图中写道

<div class="nested-fields">
  <div class="col-md-12">
    <div class="image-border">
      <div class="image-border-content">
        <div class="parent">
          <div class="image-content image-media-preview">
            <div class="font-awesome-image"><i class="far fa-image"></i></div>
          </div>
        </div>
        <label class="btn btn-light btn-sm" style="width: 100%;">
          Add a file!
          <span style="display:none;">
            <%= form.input :image, label: false, as: :file, input_html: { class:"custom-file-input", id: "ImageMedias" } %>
          </span>
        </label>
      </div>
    </div>
    <div class="links" style="margin-bottom: 10px;">
      <%= link_to_remove_association raw('<i class="far fa-trash-alt"></i> Remove'), form, class: "btn btn-light btn-sm", :style => "width: 100%; margin-top: -15px;" %>
    </div>
  </div>
</div>

然后在你的代码中做如下修改。

$("#ImageMedias").change(function () {
    if (typeof (FileReader) != "undefined") {
        let dvPreview = $(this).parents(".image-border").find(".image-media-preview");
        dvPreview.html("");
        $($(this)[0].files).each(function () {
            let file = $(this);
            let reader = new FileReader();
            reader.onload = function (e) {
                let img = $("<img />");
                img.attr("style", "width: 100%; height:auto;");
                img.attr("src", e.target.result);
                dvPreview.append(img);
            }
            reader.readAsDataURL(file[0]);
        });
    } else {
        alert("This browser does not support HTML5 FileReader.");
    }
});

所以主要的改动是

let dvPreview = $(this).parents(".image-border").find(".image-media-preview");

这将在DOM树上搜索一个父元素,其类为 image-border 然后我们在DOM中找到你的预览元素。有可能是更简单的 $(this).closest('.image-media-preview') 也能用,但我不确定。


0
投票

面临同样的问题,我用下面的代码解决了这个问题,在这里我创建了一个带有 class="upload_preview" 含有图像标签 id="preview_image" 然后,在改变事件 class="upload_image" 形成图像的领域:-

:-我在创建和编辑页面时使用了相同的形式,所以我使用了 if else 预览图的条件

<%= f.fields_for :images, f.object.images.present? ? f.object.images : f.object.images.build do |image_form| %>
    <div class="field-group">
      <div class="form-group">
        <label class="font-weight-bold">Image</label>
        <div class="upload_preview preview_style">
          <% if image_form.try(:object).try(:image).present? %>
            <img id="preview_image" class="preview_img" src="<%= image_form.try(:object).try(:image_url) %>" alt="" width="40px" height="40px" />  ## image preview
          <%else%>
            <img id="preview_image" class="preview_img" src="/assets/default-image.png" alt="" width="40px" height="40px" />  ## image preview
          <% end %>
        </div>  
        <%= image_form.file_field :image, class: "form-control upload_image"%> ## on change event
      </div>
      <div class="form-group">
        <%= image_form.link_to_remove "Delete image", class: "btn btn-danger btn-sm" %>
      </div>
    </div>
  <% end %>
  <div class="form-group">
    <%= f.link_to_add "Add more image", :images, class: "btn btn-info btn-sm" %>
  </div>

脚本代码

<script type="text/javascript">
  $(document).ready(function(){
    $(document).on('change', '.upload_image', function() {
      readURL(this);
    });
  });

 function readURL(input) {
   if (input.files && input.files[0]) {
     var reader = new FileReader();
     reader.onload = function(e) {

   $(input).siblings('.upload_preview').children('#preview_image').attr('src', e.target.result);
    }
   reader.readAsDataURL(input.files[0]);
  }
  }
</script>
© www.soinside.com 2019 - 2024. All rights reserved.