У меня есть таблица HTML. Первая строка содержит флажок. Существует метод javascript, связанный с изменением флажка. Если флажок установлен, код добавляет несколько строк в таблицу и заполняет их. Если флажок снят, код удаляет все строки, кроме первой (той, которая содержит флажок).

Первая часть кода работает нормально: строки добавляются правильно.

У меня проблема со второй частью. Вот мой код:

if (checkboxValue) {
    //Add first row
    var tr1 = document.createElement("tr");
    var td1_1 = document.createElement("td");
    ....
    tr1.appendChild(td1_1);
    var td1_2 = document.createElement("td");
    ...
    tr1.appendChild(td1_2);
    table.appendChild(tr1);

    //Add second row
    var tr2 = document.createElement("tr");
    var td2_1 = document.createElement("td");
    ...
    tr2.appendChild(td2_1);
    var td2_2 = document.createElement("td");
    ...
    tr2.appendChild(td2_2);
    table.appendChild(tr2);

} else {
    //Remove all rows but the first
    var rows = table.getElementsByTagName("tr");
    var nbrRows = rows.length;
    if (nbrRows > 1) {
        for (var i = 1; i < nbrRows; i++) {
            var row = rows[i];
            row.parentNode.removeChild(row);
        }
    }
}

Проблема всегда возникает из-за неопределенности rows[2]. Я не имею понятия почему!

Если вместо использования removeChild я напишу row.innerHTML = "", у меня будет визуальный эффект, который я ищу (все строки пропали), но это не элегантно, поскольку таблица теперь содержит несколько пустых строк (их количество увеличивается каждый раз, когда я ставлю / снимаю флажок).

Ключ? Большое спасибо за уделенное время!

2
nouklea 17 Дек 2015 в 19:20

3 ответа

Лучший ответ

Не используйте цикл for для удаления таких элементов DOM. Проблема в том, что rows является живой коллекцией, то есть он обновляется каждый раз, когда вы удаляете элементы из DOM. В результате i счетчик сдвигается , и в итоге вы попадаете в «неопределенное» место элемента.

Вместо этого используйте цикл while. Например, чтобы удалить все строки, кроме первой, которую вы можете сделать:

var rows = table.getElementsByTagName("tr");
while (rows.length > 1) {
    rows[1].parentNode.removeChild(rows[1]);
}

Также обратите внимание, что это getElementsByTagName без s.

< Сильный > UPD . Или повторите итерацию, если вам больше нравятся циклы for:

var rows = table.getElementsByTagName("tr");
for (var i = rows.length - 1; i > 0; i--) {
    rows[i].parentNode.removeChild(rows[i]);    
}

Демо: https://jsfiddle.net/9y03co6w/

2
dfsq 17 Дек 2015 в 16:40

Вы удаляете строку из массива, по которому вы перебираете. Это всегда плохая идея и, вероятно, причина вашей ошибки.

Решение: начать итерацию с конца, а не с начала.

Также см., например: пример

0
Community 23 Май 2017 в 12:30

Попробуйте заменить эту строку

var rows = table.getElementsByTagNames("tr");

От

var rows = table.find("tr");
0
j08691 17 Дек 2015 в 17:29