【问题标题】:Rails: Image preview inside a cocoon gem fieldRails:茧宝石场内的图像预览
【发布时间】:2020-05-14 08:44:40
【问题描述】:

我有一个simple form(product model),我也在使用cocoon gem 来表示我在该表单中的nested fields(attachments model)。当我创建产品时,我使用 cocoon gem 作为嵌套字段,以便创建 attachments(images) 并将它们与该产品相关联。用户可以添加茧字段并向该字段添加图像。我还在每个字段内都有一个预览,因此用户可以查看他们附加到该字段的图像。但唯一的问题是预览只显示在第一个茧字段中。如果我尝试将图像添加到另一个茧字段,则图像预览不会出现在该字段中。我希望能够添加一个茧字段,然后将图像添加到该字段并查看该字段内该图像的预览。关于如何更改代码以实现上述目标的任何想法?

这是我的设置:

<%= 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 部分:

<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 答案的细微调整让它工作。但我有一个小故障。如果我一次添加一个字段,则预览会出现在每个字段中,但如果我添加多个字段,则会出现下图中显示的问题。知道如何解决这个问题吗?

这是我正在使用的确切代码:

<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】:

你使用了一个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') 也可以,但我不确定。

【讨论】:

  • 感谢@nathanvda 的回复。我添加了上面的代码,只有第一个字段显示图像预览,当我尝试将另一个图像添加到另一个字段时没有显示。我也没有在控制台中收到任何错误。
  • 那是你以前的,对吧?您确实删除了image-content div 的id?
  • 是的,我用这个替换了整个 div:&lt;div class="image-content image-media-preview"&gt;
  • 在您的回答的帮助下,我得到了它的帮助。不过我还有一个小问题,我已经更新了我的问题,提供了有关该问题的所有详细信息,请你看看,让我知道我能做些什么来解决它。
【解决方案2】:

下面的代码解决了同样的问题,我用class="upload_preview"创建了一个div,其中包含给定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>

java脚本代码

<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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多