如何更改动态表中的特定图像?

问题描述 投票:0回答:2

我正在一张桌子上面对这种奇怪的行为,老实说,我不知道我在这里缺少什么。

我有下表:

<table>
<tr>
    <th>City</th>
    <th>Date</th>
    <th>Description</th>
    <th>Picture</th>
    <th>Sort</th>
    <th>
        <span class="table-add mb-3 mr-2">
          <a href="#!" class="text-success">
             <i class="fas fa-plus fa-2x program" aria-hidden="true"></i>
          </a>
        </span>
    </th>
</tr>
<tr>
    <td>Name</td>
    <td>01-01-20</td>
    <td>Lorem ipsum dolor sit amet.</td>
    <td>
        <div class="container-image">
            <div class="avatar-upload">
                <div class="avatar-edit">
                    <input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
                    <label for="imageUpload"></label>
                </div>
                <div class="avatar-preview">
                    <div id="imagePreview" class="imagePreview" style="background-image: url(http://i.pravatar.cc/);">
                    </div>
                </div>
            </div>
        </div>
    </td>
    <td></td>
</tr>

我有一个图标按钮来克隆我的上一个'tr',并在表格底部创建一个新的按钮。

我还有一个jquery函数将图像上传到每一行,但是由于某种原因,例如,当我在第三行中更改图像时,它将始终更新我的第一行。

<script>
function readURL(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
            $('#imagePreview').css('background-image', 'url('+e.target.result +')');
            $(this).hide();
            $(this).fadeIn(650);
        };
        reader.readAsDataURL(input.files[0]);
    }
}
$("#imageUpload").change(function() {
    readURL(this);
});

我创建了一个带有表功能示例的JSFiddle,以便为您提供有关此问题的确切概念:https://jsfiddle.net/d95yo4vg/

只需添加新行,然后尝试更改第二行的图像。

javascript jquery html dom
2个回答
1
投票

您的代码有几个问题。让我们一次遍历它们。

1。单击图片图标标签不会打开右侧输入标签的上传对话框

当添加新行时,您将在html中获得这些元素:

<input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
<label for="imageUpload"></label>

<input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
<label for="imageUpload"></label>

因为我们有多个具有相同值的id属性,所以我们违反了html5规范:https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute并且由于有多个具有相同ID的输入,因此两个标签都只会定位第一个输入。因此,即使单击第二行中的标签,我们仍将文件上传到第一个输入。

您可以通过在输入周围包裹标签来解决此问题,因此不再需要for属性:

<label>
  <input />
</label>

2。您仅在页面加载时在输入上添加一个事件侦听器这不是代码中的错误,但这是建议,以防您曾经使用javascript向页面添加新元素。

$("#imageUpload").change(...)

您正在输入上创建一个更改事件侦听器,但在页面加载时仅创建一次。因此,如果您曾经通过代码添加一个具有相同元素的新tr(没有深层克隆),则新行的输入中将没有事件侦听器。它在您的示例中确实起作用,因为您创建了tr的深层克隆。但是,这对于从AJAX响应加载并添加到文档中的元素不起作用。

我建议您改为在document上设置一个事件侦听器,并定位imageUpload子级。因为document总是存在于网页上,并且总是只有一个。

文档侦听器的代码示例:

$(document).on("change", ".imageUpload", function(e) {
  readURL(e.currentTarget);
});

3。在readURL函数中,您将第一行的imagePreview作为目标。

此问题与第一个问题的原因相同,但有另一个解决方案。我们有多个具有imagePreview id的img。因此,$('#imagePreview')选择器将仅在第一行中返回imagePreview。

要选择右行的imagePreview,您可以使用closest()函数将dom向上移动到该行中的元素。并使用find()函数返回到imagePeview。一个例子:

$(input).closest('.avatar-upload').find('.imagePreview')

关于最近]的信息:https://api.jquery.com/closest/

有关查找]的信息:https://api.jquery.com/find/


完整解决方案:

我已将您的小提琴示例分叉为一个有效的示例:https://jsfiddle.net/gkthp6qd/

问题是您已将id用作选择器,即#imagePreview

尝试使用]

$('#imagePreview').css('background-image', 'url('+e.target.result +')');

收件人

  $(event.target).parents('.avatar-upload').find('.imagePreview').css('background-image', 'url('+e.target.result +')');

Id将始终返回第一个匹配的元素

我所做的是,

捕获父项,然后捕获imagePreview元素


1
投票

问题是您已将id用作选择器,即#imagePreview

© www.soinside.com 2019 - 2024. All rights reserved.