Как изменить конкретное c изображение в динамической c таблице? - PullRequest
0 голосов
/ 26 марта 2020

Я сталкиваюсь с этим странным поведением в одной таблице и, честно говоря, я не знаю, чего мне здесь не хватает.

У меня есть следующая таблица:

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

Просто добавьте новую строку, а затем попробуйте изменить изображение второго ряда.

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Есть несколько проблем с вашим кодом. Пройдем через них go по одному.

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 spe c: https://html.spec.whatwg.org/multipage/dom.html#the -id-attribute И поскольку существует несколько входов с одинаковым идентификатором, обе метки будут только целевой первый вход. Поэтому мы продолжаем загружать файлы на первый вход, даже когда нажимаем на метку во втором ряду.

Это можно исправить, обернув метку вокруг ввода, чтобы вам не понадобилось для атрибут больше:

<label>
  <input />
</label>

2. Вы добавляете только один прослушиватель событий на входе при загрузке страницы Это не ошибка в вашем коде, но это рекомендация, если вы когда-либо добавляете новые элементы на страницу с javascript.

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

Вы создаете прослушиватель события изменения на входе, но только один раз при загрузке страницы. Поэтому, если вы когда-нибудь добавите новый tr с теми же элементами по коду (без глубокого клонирования), на входе в новой строке не будет прослушивателя событий. Это работает в вашем примере, потому что вы создаете глубокий клон tr. Но это не сработает для элементов, которые вы загружаете из ответа AJAX и добавляете в документ.

Я бы порекомендовал вам вместо этого установить прослушиватель событий на document и настроить таргетинг на imageUpload. ребенок. Поскольку документ всегда будет присутствовать на веб-странице и всегда будет только один.

Пример кода прослушивателя документов:

  • Примечание 1: Мы уже используем селектор класса здесь вместо селектора идентификатора из-за первой проблемы.
  • Примечание 2: вместо this мы анализируем e.currentTarget , потому что в селекторе документов это изменилось на document вместо imageUpload элемент. (https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget)
$(document).on("change", ".imageUpload", function(e) {
  readURL(e.currentTarget);
});

3. В функции readURL вы нацеливаетесь на imagePreview в первой строке

Эта проблема имеет ту же причину, что и первая проблема, но с другим решением. У нас есть несколько изображений с идентификатором imagePreview . Таким образом, селектор $ ('# imagePreview') будет возвращать только imagePreview в первой строке.

Чтобы выбрать imagePreview в правой строке, вы можете пройти dom до элемента в строка с функцией closest () . И вернитесь к imagePeview с помощью функции find () . Пример:

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

Информация о ближайший : https://api.jquery.com/closest/

Информация о find : https://api.jquery.com/find/


Полное решение:

Я разобрал ваш пример скрипки с рабочим примером: https://jsfiddle.net/gkthp6qd/

1 голос
/ 26 марта 2020

Проблема в том, что вы использовали id в качестве селектора, т.е. #imagePreview

Попробуйте изменить с помощью

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

На

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

Идентификатор будет всегда вернуть первый соответствующий элемент

То, что я сделал,

Поймать родительский элемент и затем поймать элемент imagePreview

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...